如何给你的AppDelegate瘦身

上篇如何把业务逻辑从ViewController中拆分出来讲了给ViewController瘦身,这篇继续讲给AppDelegate瘦身。

我见过这样的代码

Appdelegate.m

[UMSocialData setAppKey:UMENG_APPKEY];
//打开调试log的开关
[UMSocialData openLog:YES];
//向微信注册
[WXApi registerApp:WXAppId];
//设置微信AppId,设置分享url,默认使用友盟的网址
[UMSocialWechatHandler setWXAppId:WXAppId appSecret:WXAppSecret url:UMSocialShareUrl];
[UMSocialQQHandler setQQWithAppId:WXQQId appKey:WXQQKey url:UMSocialShareUrl];
// 新浪微博
[UMSocialSinaHandler openSSOWithRedirectURL:SinaRedirectURL];
//设置支持没有客户端情况下使用SSO授权
[UMSocialQQHandler setSupportWebView:YES];

基础数据
。。。
。。。

Push

......
......    

数据库

....
等等。。。。

App delegate里面一堆东西,自己看着都头疼。
因为刚开始的时候可能只是加了一个友盟分享,后来公司要加Jpush,然后继续在Appdelegate里面加,再后来......
无穷无尽的需求,然后Appdelegate不忍直视。

通过单例给AppDelegate瘦身

既然ViewController可以通过一个manager类来瘦身,是否能够运用到Appdelegate里面呢,当然可以。
类似于友盟的初始化,我们可以这么做

- (void)launchApp:(UIApplication *)application withOptions:(NSDictionary *)launchOptions {

     [UMManager getInstance];
}

然后再写一个UMManager的单例,把上面Appdelegate里面的那些友盟统计的代码在UMManager里面实现。

@implementation UMManager

+ (UMManager *)getInstance{
    static UMManager *sharedInstance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}

- (id)init{
    if (self = [super init]) {
        [self setUM];
    }
    return self;
}

- (void)setUM
{
    [UMSocialData setAppKey:UMENG_APPKEY];
    //打开调试log的开关
    [UMSocialData openLog:YES];
    //向微信注册
    [WXApi registerApp:WXAppId];
    //设置微信AppId,设置分享url,默认使用友盟的网址
    [UMSocialWechatHandler setWXAppId:WXAppId appSecret:WXAppSecret url:UMSocialShareUrl];
    [UMSocialQQHandler setQQWithAppId:WXQQId appKey:WXQQKey url:UMSocialShareUrl];
    // 新浪微博
    [UMSocialSinaHandler openSSOWithRedirectURL:SinaRedirectURL];
    //设置支持没有客户端情况下使用SSO授权
    [UMSocialQQHandler setSupportWebView:YES];
}
@end

这样AppDelegate看起来就干净多了。除此之外还有更重要的,通过Method Swizzing来给AppDelegate瘦身

通过Method Swizzing给AppDelegate瘦身

关于MethodSwizzing这里有几篇文章
Objective-C Runtime 运行时之四:Method Swizzling
Objective-C Method Swizzling 的最佳实践

@implementation AppDelegate (PushManager)

+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];
        swizzleMethod(class, @selector(application:didFinishLaunchingWithOptions:),
                      @selector(aop_application:didFinishLaunchingWithOptions:));
        swizzleMethod(class, @selector(application:didRegisterForRemoteNotificationsWithDeviceToken:),
                      @selector(aop_application:didRegisterForRemoteNotificationsWithDeviceToken:));
        swizzleMethod(class, @selector(application:didFailToRegisterForRemoteNotificationsWithError:),
                      @selector(aop_application:didFailToRegisterForRemoteNotificationsWithError:));
        swizzleMethod(class, @selector(application:didReceiveRemoteNotification:),
                      @selector(aop_application:didReceiveRemoteNotification:));
        swizzleMethod(class, @selector(application:didReceiveRemoteNotification:fetchCompletionHandler:),
                      @selector(aop_application:didReceiveRemoteNotification:fetchCompletionHandler:));
    });
}


static inline void swizzleMethod(Class class, SEL originalSelector, SEL swizzledSelector)   {
    Method originalMethod = class_getInstanceMethod(class, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
    BOOL didAddMethod =
    class_addMethod(class,
                    originalSelector,
                    method_getImplementation(swizzledMethod),
                    method_getTypeEncoding(swizzledMethod));

    if (didAddMethod) {
        class_replaceMethod(class,
                            swizzledSelector,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

- (BOOL)aop_application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [self setUpJPushManagerWithOptions:launchOptions];

    BOOL result = [self aop_application:application didFinishLaunchingWithOptions:launchOptions];

    NSDictionary *userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
    if(userInfo)
    {
        //分发
        [self pushDispatch:userInfo];
    }
    return result;
}

// push注册成功
- (void)aop_application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    [self aop_application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];

    NSUserDefaults *ud = [NSUserDefaults  standardUserDefaults];
    NSString *tokenStr = [NSString stringWithFormat:@"%@",deviceToken];
    [ud setObject:tokenStr forKey:@"deviceToken"];
    [ud synchronize];

    UI_LOG(@"deviceToken = %@", tokenStr);

    // Required
    [APService registerDeviceToken:deviceToken];
}

// push注册失败
- (void)aop_application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
    [self aop_application:application didFailToRegisterForRemoteNotificationsWithError:error];
}

// iOS7
- (void)aop_application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    [self aop_application:application didReceiveRemoteNotification:userInfo];
}

// iOS8及以上
- (void)aop_application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{  
     [self aop_application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}

......
......

有人说MethodSwzzing用起来爽,用不好的话会出问题,而且很难排查。我曾经在网上看到过这么一段话,觉着很经典。拿来分享给大家:

Method Swzzing就像是一把锋利的刀,用锋利的刀切菜固然很爽,但是容易把手切破。你不能因为刀锋利,就不用吧。相反你用钝刀风险可能更大。就像单例设计模式一样,饱受争议,但依然有很多人用它。

这里有一些StackOverFlow关于Method Swzzing的讨论。

What are the Dangers of Method Swizzling in Objective C?

总之我们要学会用好这把锋利的刀,而不是弃用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容