私は現在アプリを開発していますが、ウェブページを表示するためにブラウザを開く必要があります。そのために私は[UIApplication sharedApplication] openURL
メソッドとURL。
これはiOS 6では完全に機能しますが、iOS 7ではアプリが10秒以上フリーズしてからブラウザーが開き、すべて正常です。
これは、アドホックプロビジョニングを使用して行われます。インターネット上の誰かが、これは既知の問題であるとコメントしましたが、この問題に関して私が見つけたのは1つのコメントだけでした。
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)
}
私はiOS 7で同じ問題を見ました。私の解決策は、すでに提案されているものとほんの少しだけ異なります。 performSelector
を0.1秒の遅延で使用すると、アプリはすぐにURLを開きます。
[self performSelector:@selector(methodToRedirectToURL:) withObject:url afterDelay:0.1];
あなたが説明したのとまったく同じ症状がありました。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]];
}
上記のすべての人からのアドバイスをありがとう、これは私が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>
}
いくつかの非常に迅速なベンチマークを行った後、@ 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)
}
}
IOS 9の場合
if([[UIApplication sharedApplication] canOpenURL:url]){
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[UIApplication sharedApplication] openURL:url];
});
}
これは私のために働いたようです
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) {
}];
}
});
Swift 3.0での答えは、URLを開くことができるかどうかを確認することです。
guard let url = URL(string: myURLString) else {
return
}
if UIApplication.shared.canOpenURL(url) {
DispatchQueue.main.async {
UIApplication.shared.openURL(url)
}
}
「openURL」アクションをviewDidLoadメソッドに配置すると、実行が遅くなります。これをviewDidAppearメソッドに配置できます。または、以下のようにviewDidLoadメソッドでGCDを使用できます。
dispatch_async(dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] openURL:url];
});
OSバージョンチェック付きのSwift 4.1。
DispatchQueue.main.async() {
if #available(iOS 10.0, *) {
UIApplication.shared.open(url)
} else {
UIApplication.shared.openURL(url)
}
}
Swift3の場合
DispatchQueue.main.async {
UIApplication.shared.openURL(url)
}