调用openURL后iOS 9.3冻结

Posted

技术标签:

【中文标题】调用openURL后iOS 9.3冻结【英文标题】:iOS 9.3 freeze after calling openURL 【发布时间】:2016-03-28 07:29:39 【问题描述】:

ios 9.3 版本 13E233 和 13E234 上调用 openURL 后,我的应用程序冻结。

我尝试使用dispatch_after,但这并不能解决问题。

这是代码,没什么特别的。

+ (void)someMethod:(UIView *)senderView 

    [Utility showLoadingHUDWithText:nil inView:senderView];

    [[SomeClient sharedClient] someNetworkAPI:^(id result) 
        [Utility hideAllHUDsForView:senderView];

        NSDictionary *dict = (NSDictionary *)result;
        NSString *someString = dict[@"someKey"];
        NSURL *url = [NSURL URLWithString:someString];
        if ([[UIApplication sharedApplication] canOpenURL:url]) 
            [[UIApplication sharedApplication] openURL:url];
        
     fail:^(NSError *error) 
        [Utility hideAllHUDsForView:senderView];
        [Utility showMessageHUD:error.localizedDescription];
    ];

这似乎是一个 iOS 错误,许多其他应用也受到影响。

【问题讨论】:

你能展示你的代码吗? 可以发一下完整的功能代码吗? 我打赌这与thenextweb.com/apple/2016/03/27/…有关 我有一个非常相似的代码同样的问题。在我的所有设备上都可以正常工作,但在一些随机客户上冻结...@nix-wang HUD 保持在屏幕上而不是关闭?因为这是客户报告的内容... @sabadow 没错。但我在其他没有 HUD 的应用上发现了这个问题。 【参考方案1】:

这确实会在 iOS 9.3 的主线程上调用时导致死锁(在 iPhone 6 和 iPhone 6 Plus 上测试)。

回溯:

* thread #1: tid = 0x41840, 0x0000000180ac1014 libsystem_kernel.dylib`semaphore_wait_trap + 8, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
  * frame #0: 0x0000000180ac1014 libsystem_kernel.dylib`semaphore_wait_trap + 8
    frame #1: 0x000000010023fa20 libdispatch.dylib`_dispatch_semaphore_wait_slow + 244
    frame #2: 0x0000000180bda934 libxpc.dylib`xpc_connection_send_message_with_reply_sync + 204
    frame #3: 0x000000018276a238 MobileCoreServices`_LSStartOpenOperation + 232
    frame #4: 0x0000000182791efc MobileCoreServices`-[LSOpenOperation main] + 1160
    frame #5: 0x0000000182771bc0 MobileCoreServices`-[LSApplicationWorkspace openURL:withOptions:error:] + 472
    frame #6: 0x000000018633cdd8 UIKit`-[UIApplication _openURL:] + 356
    frame #7: 0x0000000100096c04 MyApp`__29-[ViewController someMethod]_block_invoke(.block_descriptor=0x0000000125d37e20) + 216 at ViewController.m:57
    frame #8: 0x000000010022da7c libdispatch.dylib`_dispatch_call_block_and_release + 24
    frame #9: 0x000000010022da3c libdispatch.dylib`_dispatch_client_callout + 16
    frame #10: 0x00000001002334e4 libdispatch.dylib`_dispatch_main_queue_callback_4CF + 2096
    frame #11: 0x0000000180ef8dd8 CoreFoundation`__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
    frame #12: 0x0000000180ef6c40 CoreFoundation`__CFRunLoopRun + 1628
    frame #13: 0x0000000180e20d10 CoreFoundation`CFRunLoopRunSpecific + 384
    frame #14: 0x0000000182708088 GraphicsServices`GSEventRunModal + 180
    frame #15: 0x00000001860f5f70 UIKit`UIApplicationMain + 204
    frame #16: 0x00000001000970d0 MyApp`main(argc=1, argv=0x000000016fd6fae8) + 124 at main.m:14
    frame #17: 0x00000001809be8b8 libdyld.dylib`start + 4

我发现将整个调用包装在 dispatch_async 块中解决了这个问题:

dispatch_async(dispatch_get_main_queue(), ^
    if ([[UIApplication sharedApplication] canOpenURL:url]) 
        [[UIApplication sharedApplication] openURL:url];
    
);

我会向 Apple 提交 Radar 并将其发布到 Open Radar。

看起来这已在 iOS 9.3.1 中得到修复:

修复了在 Safari 和其他应用中点击链接后导致应用无响应的问题。

【讨论】:

我在装有 iOS 9.3 的 iPhone6 上发现了同样的错误。实际上我无法使用 Safari(我无法打开链接:S),所有使用 openURL 的应用程序都会崩溃。一个例子:Slack。奇怪的是我同事的配置一样(iPhone6和iOS9.3)却没有出现错误 其实我在控制台收到这个错误:<Warning>: Error getting NanoAppRegistry workspace info: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.nanoappregistry.workspace was invalidated." UserInfo=NSDebugDescription=The connection to service named com.apple.nanoappregistry.workspace was invalidated.【参考方案2】:

我在运行 iOS 9.3.5 的 iPad Air 2 / 3 上遇到了同样的问题,而 JAL 的回答并没有为我解决问题。

下面的代码就像魅力一样。

fileprivate func letApplicationHandleUrl(_ url: URL) 

    guard UIApplication.shared.canOpenURL(url) else 

        return
    

    if #available(iOS 10.0, *) 

        UIApplication.shared.open(url, options: [:], completionHandler: nil)

     else 

        DispatchQueue.global(qos: .userInteractive).async 

            UIApplication.shared.openURL(url)
        
    

【讨论】:

以上是关于调用openURL后iOS 9.3冻结的主要内容,如果未能解决你的问题,请参考以下文章

iOS13 第三方登录 授权成功,返回app不调用openURL等方法

使用动态链接首次下载后更新应用程序时未调用 openURL 方法

iOS通过openURL打开原生应用与页面(包括电话,短信,safari等)

iOS:openURL 可以为零吗?

当从 UIActivityViewController 调用时,WhatsApp 在选择收件人后冻结

iOS 私有 API 调用将应用程序带到前台