OpenUrl затягивает приложение более 10 секунд
В настоящее время я разрабатываю приложение, которое должно открыть браузер для отображения веб-страницы.
Для этого я использую метод [UIApplication sharedApplication] openURL
с URL-адресом.
В iOS 6 это работает отлично, но в iOS 7 оно замораживает приложение на 10 + секунд, затем открывается браузер, и все хорошо.
Это происходит с использованием специального выделения. Кто-то в Интернете заметил, что это была известная проблема, однако, что один комментарий был всем, что я мог найти относительно этой проблемы.
Ответы
Ответ 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)
}