Приложение Lauching с URL (через UIApplicationDelegate handleOpenURL), работающее под iOS 4, но не под iOS 3.2
Я внедрил UIApplicationDelegate
application:didFinishLaunchingWithOptions:
и
application:handleOpenURL:
согласно спецификации, то есть
application:didFinishLaunchingWithOptions:
returns YES
и
application:handleOpenURL: opens the URL.
Код работает под iOS 4 (в обоих случаях, то есть при запуске приложения и при его активации из приостановленного состояния). Тем не менее, код не работает в iOS 3.2.
Ответы
Ответ 1
Я даю ответ на свой вопрос. Выяснение решения заняло у меня некоторое время и было довольно неприятным. Если вы выполняете поиск в Интернете, вы найдете некоторые частичные ответы, но мне все же понадобилось некоторое время, чтобы выработать следующее решение, и я надеюсь, что это добавит некоторую ясность.
Итак, рекомендуемое поведение вашего приложения выглядит следующим образом (см. Открытие поддерживаемых типов файлов в iOS Ref Lib):
- Не используйте
applicationDidFinishLaunching:
(см. примечание в UIApplicationDelegate).
- Внесите
application:didFinishLaunchingWithOptions:
и проверьте URL-адрес, верните YES, если вы можете его открыть, иначе НЕТ, но не открывайте его.
- Внесите
application:handleOpenURL:
и откройте URL-адрес, верните YES в случае успеха, иначе NO.
В iOS 4 передача URL-адреса в приложение приводит к одному из следующих двух способов:
- Если приложение запущено, вызывается
application:didFinishLaunchingWithOptions:
и вызывается application:handleOpenURL:
, если и application:didFinishLaunchingWithOptions:
возвращается YES.
- Если приложение становится активным из приостановленного состояния, тогда
application:didFinishLaunchingWithOptions:
не вызывается, а вызывается application:handleOpenURL:
.
Однако в iOS 3.2 кажется, что application:handleOpenURL:
никогда не вызывается! Подсказка о том, что поведение отличается от iOS 3.2, можно найти в Обработка запросов URL. Там вы обнаружите, что application:handleOpenURL:
вызывается, если application:didFinishLaunchingWithOptions:
не реализовано, но applicationDidFinishLaunching:
реализовано. Но application:handleOpenURL:
не вызывается, если выполняется application:didFinishLaunchingWithOptions:
.
Следовательно, одним из решений для работы кода под 3.2 и 4.0 является:
- Откройте URL-адрес в
application:didFinishLaunchingWithOptions:
, но затем верните NO, чтобы предотвратить вызов application:handleOpenURL:
.
- Откройте URL-адрес в
application:handleOpenURL:
, если вам меньше 4.0, и приложение находится в состоянии приостановлено.
Я нашел это решение в другом посте, но я был в замешательстве, потому что это противоречило рекомендации в документации iOS Ref Lib (а именно, что мы должны вернуть ДА в application:didFinishLaunchingWithOptions:
). (В этот момент я не понимал, что документация противоречит ему).
Я считаю, что текущее поведение iOS 4.0 будет будущим поведением, я предпочитаю следующее решение:
- Не используйте
applicationDidFinishLaunching:
.
- Внесите
application:didFinishLaunchingWithOptions:
и проверьте URL-адрес, верните YES, если вы можете его открыть, иначе НЕТ, но не открывайте его. Если мы находимся на 3.2, откройте URL.
- Внесите
application:handleOpenURL:
и откройте URL-адрес, верните YES в случае успеха, иначе NO.
Итак, вкратце, я реализую поведение iOS 4 и добавил следующую строку в application:didFinishLaunchingWithOptions:
if([[[UIDevice currentDevice] systemVersion] hasPrefix:@"3.2"]) {
[self application:application handleOpenURL:url];
}
которые делают код работать под 3.2.
Ответ 2
application:handleOpenURL:
теперь DEPRECATED.
Как и в iOS 4.2, вы можете использовать это для открытия URL-адресов:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
Документация:
https://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIApplicationDelegate_Protocol/Reference/Reference.html
Ответ 3
Я начал писать приложение, которое использовало Dropbox api. Чтобы понять концепцию, я запустил пример приложения, используя мой ключ/секрет, упомянутый в документации Dropbox/Developer .
Когда образец приложения начал работать, я использовал те же ключевые/секретные значения для моего приложения.
Для примера приложения реализация handleOpenURL (или openURL на iOS 4.2) выполняется, как и ожидалось. По какой-то странной причине это было не для моего приложения. Мое приложение появилось в фоновом режиме, чтобы отобразить страницу входа в систему и страницу проверки подлинности dropbox. После успешного входа в систему и проверки подлинности мое приложение никогда не выходило на передний план. Это было верно и для платформы Simulator, и для устройства (iPad).
Я попробовал почти все, перечисленные в интернете, включая этот пост. Благодарю. Однако успеха не было.
Наконец, он НАЧАЛО работает для моего приложения, когда я делал следующее:
- В симуляторе выберите "iOS Simulator → Reset" Содержание и настройки "и reset.
- На устройстве я удалил пример исполняемого приложения, связанного с приложением, и который, в свою очередь, связал с ним кеш.
Ответ 4
Добавьте в конец application:DidFinishLaunchingWithOptions
следующее:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
NSURL *url = (NSURL *)[launchOptions valueForKey:UIApplicationLaunchOptionsURLKey];
if (url != nil && [url isFileURL]) {
return YES;
} else return NO;
} // End of application:didFinishLaunchingWithOptions:
// New method starts
-(BOOL) application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
mvc = [nc.viewControllers objectAtIndex:0];
if (url != nil && [url isFileURL]) {
[mvc handleOpenURL:url];
}
return YES;
}
где mvc - мой основной ViewController, и nc мой навигационный контроллер.
Затем в MainViewController сделайте следующее:
- (void)handleOpenURL:(NSURL *)url {
[self.navigationController popToRootViewControllerAnimated:YES];
// Next bit not relevant just left in as part of the example
NSData *jsonData = [NSData dataWithContentsOfURL:url];
NSError *error;
NSDictionary *dictionary = [[NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error] objectAtIndex:0];
[self managedObjectFromStructure:dictionary withManagedObjectContext:self.context];
...
}
после объявления handleOpenURL в .h, конечно.
Спасибо Кристиану за то, что он прилагал усилия для этого.