OpenUrl冻结应用程序超过10秒

时间:2013-10-14 08:46:43

标签: ios ios7 openurl

我目前正在开发一款需要打开浏览器才能显示网页的应用。 为此,我使用[UIApplication sharedApplication] openURL方法和网址。

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

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

11 个答案:

答案 0 :(得分:91)

我从Application Delegate didReceiveRemoteNotification:或didFinishLaunchingWithOptions调用 - [UIApplication openUrl:]时发现了同样的问题:自iOS 7以来。

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

// objc
dispatch_async(dispatch_get_main_queue(), ^{
    [[UIApplication sharedApplication] openURL:url];
});

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

这适合你吗?

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

// swift
dispatch_async(dispatch_get_main_queue()) {
    UIApplication.sharedApplication().openURL(url)
}

答案 1 :(得分:10)

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

[self performSelector:@selector(methodToRedirectToURL:) withObject:url afterDelay:0.1];

答案 2 :(得分:9)

与您描述的完全相同的症状:在iOS6上正常工作,但在iOS7上持续约10秒。原来是一个线程问题。

我们直接从AppDelegate方法[UIApplication sharedApplication] openURL发出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]];
}

答案 3 :(得分: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));
            });
        });
 }

}

答案 4 :(得分:4)

在做了一些非常快速的基准测试后,我发现@lidsinkers方法显然是最快的。特别是当我用0.1替换0.001的延迟时。

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

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.001 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
            UIApplication.sharedApplication().openURL(url)
        }

完整方法:

/// 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)
        }
    }

答案 5 :(得分:3)

对于ios 9

if([[UIApplication sharedApplication] canOpenURL:url]){            
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [[UIApplication sharedApplication] openURL:url];
        });
    }

这似乎对我有用

答案 6 :(得分:1)

我发现从iOS 10开始使用它会更好。

dispatch_async(dispatch_get_main_queue(), ^{
    if ([[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:@"."].firstObject integerValue] < 10) {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel:..."]];
    } else {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel:..."] options:@{} completionHandler:^(BOOL success) {

        }];
    }
});

答案 7 :(得分:0)

如果你把&#34; openURL&#34; viewDidLoad方法中的操作,然后肯定会慢慢执行。您可以将它放在viewDidAppear方法中。或者,您可以在viewDidLoad方法中使用GCD,如下所示:

dispatch_async(dispatch_get_main_queue(), ^{
    [[UIApplication sharedApplication] openURL:url];
});

答案 8 :(得分:0)

以下是Swift 3.0中的答案,并检查我们是否可以打开URL。

guard let url = URL(string: myURLString) else {
    return
}


if UIApplication.shared.canOpenURL(url) {
   DispatchQueue.main.async {
     UIApplication.shared.openURL(url)
   }
}

答案 9 :(得分:0)

带有操作系统版本检查的Swift 4.1。

DispatchQueue.main.async() {
  if #available(iOS 10.0, *) {
    UIApplication.shared.open(url)
  } else {
    UIApplication.shared.openURL(url)
  }
}

答案 10 :(得分:0)

对于Swift3

    DispatchQueue.main.async {
        UIApplication.shared.openURL(url)
    }