接下来就到了进入注册界面,我们来看看如何构建好这一块:
来到了ViewControllers,需要引入一个非常非常重要的概念,基类控制器
总所周知,控制器各式各样,根据面向对象的思想,我们需要一个基类来装载它们的共性和一些共有的操作
我们首先引入:NavgationController的基类:
#import <UIKit/UIKit.h>
@interface BaseNavigationController : UINavigationController
@end
实现:
#import "BaseNavigationController.h"
@implementation BaseNavigationController
- (BOOL)shouldAutorotate{
return [self.visibleViewController shouldAutorotate];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return [self.visibleViewController preferredInterfaceOrientationForPresentation];
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
if (![self.visibleViewController isKindOfClass:[UIAlertController class]]) {//iOS9 UIWebRotatingAlertController
return [self.visibleViewController supportedInterfaceOrientations];
}else{
return UIInterfaceOrientationMaskPortrait;
}
}
@end
很明显,CodingNet只将一些屏幕方向的方法集成于Navigation的基类当中。
继续看另外一个基类控制器:
头文件:
#import <UIKit/UIKit.h>
@interface BaseViewController : UIViewController
- (void)tabBarItemClicked;
- (void)loginOutToLoginVC;
+ (void)handleNotificationInfo:(NSDictionary *)userInfo applicationState:(UIApplicationState)applicationState;
+ (UIViewController *)analyseVCFromLinkStr:(NSString *)linkStr;
+ (void)presentLinkStr:(NSString *)linkStr;
+ (UIViewController *)presentingVC;
+ (void)presentVC:(UIViewController *)viewController;
@end
可以看到,主要集中在几个关键的领域:
1.消息处理
2.跳转链接处理
3.跳转控制器处理
1.消息处理:
#pragma mark Notification
+ (void)handleNotificationInfo:(NSDictionary *)userInfo applicationState:(UIApplicationState)applicationState{
if (applicationState == UIApplicationStateInactive) {
//If the application state was inactive, this means the user pressed an action button from a notification.
//标记为已读
NSString *notification_id = [userInfo objectForKey:@"notification_id"];
if (notification_id) {
[[Coding_NetAPIManager sharedManager] request_markReadWithCodingTipIdStr:notification_id andBlock:^(id data, NSError *error) {
}];
}
//弹出临时会话
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
DebugLog(@"handleNotificationInfo : %@", userInfo);
NSString *param_url = [userInfo objectForKey:@"param_url"];
[self presentLinkStr:param_url];
});
}else if (applicationState == UIApplicationStateActive){
// NSString *param_url = [userInfo objectForKey:@"param_url"];
// [self analyseVCFromLinkStr:param_url analyseMethod:AnalyseMethodTypeJustRefresh isNewVC:nil];
//标记未读
UIViewController *presentingVC = [BaseViewController presentingVC];
if ([presentingVC isKindOfClass:[Message_RootViewController class]]) {
[(Message_RootViewController *)presentingVC refresh];
}
[[UnReadManager shareManager] updateUnRead];
}
}
代码实现很简单,如果状态是Inactive,请求服务器一次,并弹出临时回话
如果状态是active直接弹出到相应的目标控制器
来看看哪里调用了这个方法,其实心里也肯定知道,无非在消息处理相关处:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
DebugLog(@"didReceiveRemoteNotification-userInfo:-----\n%@", userInfo);
[XGPush handleReceiveNotification:userInfo];
[BaseViewController handleNotificationInfo:userInfo applicationState:[application applicationState]];
}
2.跳转链接处理
接下来这个方法就十分复杂了:
+ (UIViewController *)analyseVCFromLinkStr:(NSString *)linkStr;
但是不要害怕,因为其实说白了就是解析linkStr来获取(或生成)相应的控制器,然后跳转
只要和服务器的交互到位,也没什么问题。相当于一个通用的调用轮子。
3.跳转控制器处理:
接下来这个很有仔细分析的必要:
+ (UIViewController *)presentingVC{
UIWindow * window = [[UIApplication sharedApplication] keyWindow];
if (window.windowLevel != UIWindowLevelNormal)
{
NSArray *windows = [[UIApplication sharedApplication] windows];
for(UIWindow * tmpWin in windows)
{
if (tmpWin.windowLevel == UIWindowLevelNormal)
{
window = tmpWin;
break;
}
}
}
UIViewController *result = window.rootViewController;
while (result.presentedViewController) {
result = result.presentedViewController;
}
if ([result isKindOfClass:[RootTabViewController class]]) {
result = [(RootTabViewController *)result selectedViewController];
}
if ([result isKindOfClass:[UINavigationController class]]) {
result = [(UINavigationController *)result topViewController];
}
return result;
}
先来看看这个presenting 和 presented 的概念:
参考:
http://www.cnblogs.com/smileEvday/archive/2012/05/29/presentModalViewController.html
presenting即弹出别人的载体,而presented即被弹出的对象
搞清楚这个之后就会非常轻松了
这个方法就是先找到普通level层级的窗口,一些临时弹出的高级别和状态栏级别的忽略掉
然后遍历presented视图控制器,目的是保持它最前面的控制器状态,如果是tabBarController则选择被选中的tarBar栏
如果是NavigationController,则选择栈中最前的那个。
看CodingNet的大牛这种统筹方式实在真心受教。这种调用逻辑,清晰,严谨,全局。