CodingNet - Learning - 4

接下来就到了进入注册界面,我们来看看如何构建好这一块:

来到了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]];
}


这个就是CodingNet的推送处理相关的代码


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的大牛这种统筹方式实在真心受教。这种调用逻辑,清晰,严谨,全局。







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值