背景
最近遇到个问题,当Xcode
升级到16,且设备升级到iOS 18
后,使用微信分享无法调起微信,控制台输出:
BUG IN CLIENT OF UIKIT: The caller of UIApplication.openURL(_:) needs to migrate to the non-deprecated UIApplication.open(_:options:completionHandler:). Force returning false (NO).
这个问题原因很简单,是因为在iOS 18
以后,openURL:
完全被弃用,需要用openURL:options:completionHandler:
替代。
实际上在iOS10
以后,Apple
就已经在Xcode
中提示openURL:
将会被弃用,需要用openURL:options:completionHandler:
替代。但实际上在iOS 17
之前openURL:
一直是可以用的,所以很多开发者包括很多知名的 SDK
都忽略了,直到本次iOS 18
完全弃用,导致问题的出现。
解决方案
解决方案也很简单:
1.如果代码是自己的写的,全文搜索并替换相关方法即可。
2.如果是第三方SDK
,更新SDK
即可。或者手动替换SDK里面相关方法。
特例
我遇到的问题比较奇葩,是某个第三方SDK
里面出现了openURL:
方法,但是这个SDK
已经完全停止维护,几年不更新了,而且这个SDK
不是源码模式,而是编译成了.a
文件,根本没办法看到他的代码,更没办法手动替换它的代码,这特么就尴尬了。找了很久,终于找到替代方案,那就是利用runtime
来替换相关方法。
Objective-C
版本参考以下方案:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
[AppDelegate hookOldOpenUrl:AppDelegate.class];
}
- (BOOL)g_openURL:(NSURL*)url{
[UIApplication.sharedApplication openURL:url options:nil completionHandler:nil];
return YES;
}
+ (void)hookOldOpenUrl:(Class)targetCls{
Class cls = [UIApplication class];
if (cls) {
Method originalMethod =class_getInstanceMethod(cls, @selector(openURL:));
Method swizzledMethod =class_getInstanceMethod(targetCls, @selector(g_openURL:));
if (!originalMethod || !swizzledMethod) {
return;
}
IMP originalIMP = method_getImplementation(originalMethod);
IMP swizzledIMP = method_getImplementation(swizzledMethod);
const char *originalType = method_getTypeEncoding(originalMethod);
const char *swizzledType = method_getTypeEncoding(swizzledMethod);
class_replaceMethod(cls,@selector(openURL:),swizzledIMP,swizzledType);
class_replaceMethod(cls,@selector(g_openURL:),originalIMP,originalType);
}
}
Swift
版本参考以下方案:
func hookOldOpenUrl(tragetCls:AnyClass){
let cls = UIApplication.self
let originalSelector = #selector(UIApplication.openURL(_:))
let swizzledSelector = #selector(g_openURL)
let originalMethod = class_getInstanceMethod(cls, originalSelector)
let swizzledMethod = class_getInstanceMethod(tragetCls, swizzledSelector)
let didAddMethod: Bool = class_addMethod(cls, originalSelector, method_getImplementation(swizzledMethod!), method_getTypeEncoding(swizzledMethod!))
if didAddMethod {
class_replaceMethod(cls, swizzledSelector, method_getImplementation(originalMethod!), method_getTypeEncoding(originalMethod!))
} else {
method_exchangeImplementations(originalMethod!, swizzledMethod!)
}
}
@objc func g_openURL(url:URL)->Bool{
UIApplication.shared.open(url)
return true
}
再次运行即可修复该问题。