Подтвердить что ты не робот

OpenUrl затягивает приложение более 10 секунд

В настоящее время я разрабатываю приложение, которое должно открыть браузер для отображения веб-страницы. Для этого я использую метод [UIApplication sharedApplication] openURL с URL-адресом.

В iOS 6 это работает отлично, но в iOS 7 оно замораживает приложение на 10 + секунд, затем открывается браузер, и все хорошо.

Это происходит с использованием специального выделения. Кто-то в Интернете заметил, что это была известная проблема, однако, что один комментарий был всем, что я мог найти относительно этой проблемы.

4b9b3361

Ответ 1

Я заметил ту же проблему при вызове - [UIApplication openUrl:] из делегирования приложения didReceiveRemoteNotification: или didFinishLaunchingWithOptions: с iOS 7.

Я решил это, немного задержав вызов с помощью GCD:

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

Это позволило iOS некоторое время для завершения инициализации приложения, и вызов затем выполняется без каких-либо проблем. Не спрашивайте меня, почему.

Это работает для вас?

Поскольку этот ответ часто встречается, я добавил быструю версию:

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

Ответ 2

Я видел ту же проблему в iOS 7. Мое решение немного отличается от уже предложенного. Используя performSelector всего за 0,1 секунды, приложение сразу же открывает URL-адрес.

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

Ответ 3

Если бы те же самые симптомы, которые вы описали: отлично работали на iOS6, но ~ 10 секунд зависали на iOS7. Оказывается, это проблема с потоками.

Мы отправляли [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]];
}

Ответ 4

Спасибо за совет от всех ребят выше, вот как я решил это в 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));
            });
        });
 }

}

код >

Ответ 5

Сделав очень быстрый бенчмаркинг, я нашел метод @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)
        }
    }

Ответ 6

Для ios 9

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

это, похоже, сработало для меня

Ответ 7

Я нашел, что будет лучше использовать это с 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) {

        }];
    }
});

Ответ 8

Если вы поместите действие "openURL" в методе viewDidLoad, то он обязательно будет выполняться медленно. Вы можете поместить его в метод viewDidAppear. Или вы можете использовать GCD в методе viewDidLoad, как показано ниже:

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

Ответ 9

Вот ответ в Swift 3.0 с проверкой, можно ли открыть URL-адрес или нет.

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


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

Ответ 10

Swift 4.1 с проверкой версии ОС.

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

Ответ 11

Для Swift3

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