web-dev-qa-db-ja.com

OpenUrlがアプリを10秒以上フリーズする

私は現在アプリを開発していますが、ウェブページを表示するためにブラウザを開く必要があります。そのために私は[UIApplication sharedApplication] openURLメソッドとURL。

これはiOS 6では完全に機能しますが、iOS 7ではアプリが10秒以上フリーズしてからブラウザーが開き、すべて正常です。

これは、アドホックプロビジョニングを使用して行われます。インターネット上の誰かが、これは既知の問題であるとコメントしましたが、この問題に関して私が見つけたのは1つのコメントだけでした。

41
smoove

IOS 7以降、アプリケーションデリゲートdidReceiveRemoteNotification:またはdidFinishLaunchingWithOptions:から-[UIApplication openUrl:]を呼び出すときに同じ問題が発生しました。

GCDを使用して呼び出しを少し遅延させることで解決しました。

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

これにより、iOSがアプリケーションの初期化を完了するまでしばらく時間がかかり、呼び出しは問題なく実行されます。理由を聞かないでください。

これはうまくいきますか?

この答えはよく見られるため、Swift version:

// Swift
dispatch_async(dispatch_get_main_queue()) {
    UIApplication.sharedApplication().openURL(url)
}
93
kamidude

私はiOS 7で同じ問題を見ました。私の解決策は、すでに提案されているものとほんの少しだけ異なります。 performSelectorを0.1秒の遅延で使用すると、アプリはすぐにURLを開きます。

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

あなたが説明したのとまったく同じ症状がありました。iOS6では問題なく動作しましたが、iOS7では最大10秒ハングしました。スレッドの問題であることが判明しました。

AppDelegateメソッドapplicationDidBecomeActive()から直接[UIApplication sharedApplication] openURLを発行していました。これをバックグラウンドスレッドに移動すると、問題がすぐに解決しました。

- (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]];
}
9
colminator

上記のすべての人からのアドバイスをありがとう、これは私が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));
            });
        });
 }
</ code>

}
6
Has AlTaiar

いくつかの非常に迅速なベンチマークを行った後、@ 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
Jacob R

IOS 9の場合

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

これは私のために働いたようです

3
Zaartha

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) {

        }];
    }
});
1
Lumialxk

Swift 3.0での答えは、URLを開くことができるかどうかを確認することです。

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


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

「openURL」アクションをviewDidLoadメソッドに配置すると、実行が遅くなります。これをviewDidAppearメソッドに配置できます。または、以下のようにviewDidLoadメソッドでGCDを使用できます。

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

OSバージョンチェック付きのSwift 4.1。

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

Swift3の場合

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