今天在用 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 是不是这样的思路