OpenUrl冻结应用程序超过10秒

smo*_*ove 41 openurl ios ios7

我目前正在开发一个应用程序,需要打开浏览器才能显示网页.要做到这一点,我使用该[UIApplication sharedApplication] openURL方法与网址.

在iOS 6中,这可以很好地工作,但在iOS 7中将应用程序冻结10秒以上,然后打开浏览器,一切都很好.

使用临时配置会发生这种情况.互联网上的某个人评论说这是一个已知的问题,然而,我可以找到一个关于这个问题的评论.

kam*_*ude 92

从iOS 7开始,从Application Delegate didReceiveRemoteNotification:或didFinishLaunchingWithOptions调用 - [UIApplication openUrl:]时,我注意到了同样的问题.

我通过使用GCD延迟调用来解决它:

// objc
dispatch_async(dispatch_get_main_queue(), ^{
    [[UIApplication sharedApplication] openURL:url];
});
Run Code Online (Sandbox Code Playgroud)

它让iOS有一段时间来完成应用程序初始化,然后执行调用没有任何问题.不要问我为什么.

这对你有用吗?

由于经常看到这个答案,我添加了swift版本:

// swift
dispatch_async(dispatch_get_main_queue()) {
    UIApplication.sharedApplication().openURL(url)
}
Run Code Online (Sandbox Code Playgroud)

  • 仅供参考,此解决方法似乎不再适用于iOS 9.我还看到延迟可能导致崩溃,因为"10.00秒后无法进行场景更新".将URL的开头移动到后台线程确实可以解决问题,因此将dispatch_get_main_queue更改为dispatch_get_global_queue可以完成这项工作. (5认同)
  • 你有没有找到导致这种情况的根本原因?解决这个就像放一个"补丁"...我想知道这是什么原因. (2认同)

lid*_*ker 10

我在iOS 7中看到了同样的问题.我的解决方案与已经提出的解决方案略有不同.通过performSelector仅使用0.1秒的延迟,应用程序立即打开URL.

[self performSelector:@selector(methodToRedirectToURL:) withObject:url afterDelay:0.1];
Run Code Online (Sandbox Code Playgroud)


col*_*tor 9

有与你描述的完全相同的症状:在iOS6上运行良好,但在iOS7上运行约10秒.原来是一个线程问题.

我们[UIApplication sharedApplication] openURL直接从AppDelegate方法发出 applicationDidBecomeActive().将此移至后台线程可立即解决问题:

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    ...

    // hangs for 10 seconds
    // [[UIApplication sharedApplication] openURL:[NSURL URLWithString: url]];

    // Fix: use threads!
    [NSThread detachNewThreadSelector:@selector(openbrowser_in_background:) toTarget:self withObject:url];

    ...
}

- (void)openbrowser_in_background:(NSString *)url
{
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString: url]];
}
Run Code Online (Sandbox Code Playgroud)

  • @JustSid` [UIApplication sharedApplication] openURL:...]`OP正在使用的API导致上下文切换到另一个应用程序(在这种情况下为Safari) - 这本身就是一项昂贵的操作.创建线程的成本<1ms?一直保存可能的10*秒*超时是一个非常好的交易. (7认同)

Has*_*iar 6

感谢上面所有人的建议,这就是我在Xamarin.iOS(以及Xamarin.Forms)中解决它的方法.解决方案的灵感来自上面讨论过的人,并希望它能帮助其他人面对同样的问题但使用Xamarin.


[Register("AppDelegate")]
public class AppDelegate
{
     ....

 public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
 {
      // We do some logic to respond to launching app, and return to that app. 
      Task.Delay(500).ContinueWith(_ => {
            this.InvokeOnMainThread( () => {
                UIApplication.SharedApplication.OpenUrl(NSUrl.FromString(openUri));
            });
        });
 }
Run Code Online (Sandbox Code Playgroud)

}


Jac*_*b R 5

在进行了非常快速的基准测试之后,我发现@lidsinkers方法显然是最快的。特别是当我用代替延迟0.10.001

因此,我决定将其转换为Swift代码:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.001 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
            UIApplication.sharedApplication().openURL(url)
        }
Run Code Online (Sandbox Code Playgroud)

完整方法:

/// An attempt at solving 'openUrl()' freeze problem
func lidsinkerOpenURL(url: NSURL) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.001 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
            UIApplication.sharedApplication().openURL(url)
        }
    }
Run Code Online (Sandbox Code Playgroud)