美文网首页iOS开发iOS plus
OC 中如何做到分类方法不覆盖原方法

OC 中如何做到分类方法不覆盖原方法

作者: Seimda | 来源:发表于2017-06-15 22:34 被阅读471次

今天在用 ShareSDK 做第三方登录的时候,发现使用旧版 SDK 时是在 AppDelegate.m 文件里手动实现 2 个处理客户端返回消息的回调方法,如下图

而新版 SDK 却不需要。那么问题来了,新版是在哪里实现处理客户端返回消息的回调方法?

要知道,处理回跳必须需要实现以下方法

iOS 9 以下用这个

-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(id)annotation

iOS 9 及以上用这个

-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options

我猜想 ShareSDK 是用 AppDelegate 的分类实现了方法,但一般情况下,在OC中只要分类实现了方法,那么类中的原来实现方法就不会被调用。 而现在这个方法我们可以自定义实现,且不影响第三方客户端回跳,怎么做???

其实要做到分类方法不覆盖原方法需要用的 OC 的 Runtime ,来测试一下

在 AppDelegate.m 中实现 applicationDidBecomeActive:

- (void)applicationDidBecomeActive:(UIApplication *)application {
    NSLog(@"applicationDidBecomeActive");
}

再创建一个 AppDelegate 的分类,实现applicationDidBecomeActive:

- (void)applicationDidBecomeActive:(UIApplication *)application {
    NSLog(@"applicationDidBecomeActive--分类");
    Class currentClass = [AppDelegate class];
    if (currentClass) {
        unsigned int methodCount;
        Method *methodList = class_copyMethodList(currentClass, &methodCount);
        IMP lastImp = NULL;
        SEL lastSel = NULL;
        for (NSInteger i = 0; i < methodCount; i++) {
            Method method = methodList[i];
            NSString *methodName = [NSString stringWithCString:sel_getName(method_getName(method))
                                                      encoding:NSUTF8StringEncoding];
            if ([@"applicationDidBecomeActive:" isEqualToString:methodName]) {
                lastImp = method_getImplementation(method);
                lastSel = method_getName(method);
            }
        }
        typedef void (*fn)(id,SEL,id);
        if (lastImp != NULL) {
            fn f = (fn)lastImp;
            f(self,lastSel,application);
        }
        free(methodList);
    }
}

打印结果

2017-06-15 21:55:45.709 demo[807:25011] applicationDidBecomeActive--分类
2017-06-15 21:55:45.709 demo[807:25011] applicationDidBecomeActive

这样,就可以同时调用分类和原类的方法了,不知道 ShareSDK 是不是这样的思路

参考

对OC中Category 的理解,以及方法覆盖的解决办法

相关文章

网友评论

  • 承宇:你好,我想写个方法给其他人调用的话。要是别人把Appdelegate这个文件名称改了,我的Appdelegate分类就不好用了。针对这个问题的话,ShareSDK是如何处理的呢?
  • 谦言忘语:试过下,楼主的方法确实可以。但是如果多个分类同时覆盖了原方法,那么只会有一个分类的方法和原方法被调用,这个问题不好解决啊
    Seimda:不知道你注意到 lastImp 变量没,示例代码中, lastImp 只是取了这个方法的最后一个实现,即原方法的实现。同理,你可以取到其他任意多个分类中方法的实现,然后调用就可以了。不过,要注意各分类方法调用的先后顺序

本文标题:OC 中如何做到分类方法不覆盖原方法

本文链接:https://www.haomeiwen.com/subject/cqnuqxtx.html