使用 URL 启动应用程序(通过 UIApplicationDelegate 的 handleOpenURL)在 iOS 4 下工作,但不在 iOS 3.2 下
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3612460/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Lauching App with URL (via UIApplicationDelegate's handleOpenURL) working under iOS 4, but not under iOS 3.2
提问by Christian Fries
I have implemented UIApplicationDelegate's
我已经实现了 UIApplicationDelegate 的
application:didFinishLaunchingWithOptions:
and
和
application:handleOpenURL:
according to specification, i.e.,
根据规范,即
application:didFinishLaunchingWithOptions:
returns YES
and
和
application:handleOpenURL: opens the URL.
The code works under iOS 4 (in both cases, i.e., when the app is launched and when it becomes active from suspended state). However, the code does not work under iOS 3.2.
该代码适用于 iOS 4(在这两种情况下,即应用程序启动时和从挂起状态变为活动状态时)。但是,该代码在 iOS 3.2 下不起作用。
回答by Christian Fries
I give an answer to my own question. Finding out the solution took me a while and was quite frustrating. If you do an internet search you find some partial answers, but it still took me a while to work out the following solution and I do hope it adds some clarity.
我回答我自己的问题。找到解决方案花了我一段时间并且非常令人沮丧。如果您进行互联网搜索,您会找到一些部分答案,但我仍然花了一些时间来制定以下解决方案,我希望它能增加一些清晰度。
So first, the recommended behavior of your app appears to be the following (see Opening Supported File Typesin iOS Ref Lib):
因此,首先,您的应用程序的推荐行为如下(请参阅在 iOS 参考库中打开支持的文件类型):
- Do not implement
applicationDidFinishLaunching:
(see the note at UIApplicationDelegate). - Implement
application:didFinishLaunchingWithOptions:
and check the URL, return YES if you can open it, otherwise NO, but do not open it. - Implement
application:handleOpenURL:
and open the URL, return YES if successful, otherwise NO.
- 不要实现
applicationDidFinishLaunching:
(请参阅UIApplicationDelegate 中的注释)。 - 实现
application:didFinishLaunchingWithOptions:
并检查URL,如果可以打开则返回YES,否则返回NO,但不要打开它。 - 实现
application:handleOpenURL:
并打开URL,成功则返回YES,否则返回NO。
In iOS 4, passing an URL to an app results in one of the following two behaviors:
在 iOS 4 中,将 URL 传递给应用程序会导致以下两种行为之一:
- If the app is launched then
application:didFinishLaunchingWithOptions:
is called andapplication:handleOpenURL:
is called if andapplication:didFinishLaunchingWithOptions:
returned YES. - If the app is becoming active from suspended state then
application:didFinishLaunchingWithOptions:
is not called butapplication:handleOpenURL:
is called.
- 如果应用程序已启动,则
application:didFinishLaunchingWithOptions:
调用并application:handleOpenURL:
调用 if 并application:didFinishLaunchingWithOptions:
返回 YES。 - 如果应用程序从挂起状态变为活动状态,则
application:didFinishLaunchingWithOptions:
不会调用而是application:handleOpenURL:
调用。
However, in iOS 3.2 it appears as if application:handleOpenURL:
is never called! A hint that the behavior is different under iOS 3.2 can be found in Handling URL Requests. There you find that application:handleOpenURL:
is called if application:didFinishLaunchingWithOptions:
is not implemented, but applicationDidFinishLaunching:
is implemented. But application:handleOpenURL:
is not called if application:didFinishLaunchingWithOptions:
is implemented.
但是,在 iOS 3.2 中,它似乎application:handleOpenURL:
从未被调用过!在处理 URL 请求中可以找到在 iOS 3.2 下行为不同的提示。在那里你会发现application:handleOpenURL:
调用 ifapplication:didFinishLaunchingWithOptions:
没有实现,但是applicationDidFinishLaunching:
被实现了。但application:handleOpenURL:
如果application:didFinishLaunchingWithOptions:
实现则不调用。
Hence, one solution to make the code work under 3.2 and 4.0 is:
因此,使代码在 3.2 和 4.0 下工作的一种解决方案是:
- Open the URL in
application:didFinishLaunchingWithOptions:
, but then return NO to prevent thatapplication:handleOpenURL:
is called. - Open the URL in
application:handleOpenURL:
, in case you are under 4.0 and the app was in suspended state.
- 打开 中的 URL
application:didFinishLaunchingWithOptions:
,然后返回 NO 以防止application:handleOpenURL:
调用。 - 打开 中的 URL
application:handleOpenURL:
,以防您在 4.0 以下并且应用程序处于暂停状态。
I found this solution in another post, but I was confused, because it contradicted the recommendation in iOS Ref Lib documentation (namely that we should return YES in application:didFinishLaunchingWithOptions:
). (At that point I did not realize that the documentation contradicts it self).
我在另一篇文章中找到了这个解决方案,但我很困惑,因为它与 iOS Ref Lib 文档中的建议相矛盾(即我们应该在 中返回 YES application:didFinishLaunchingWithOptions:
)。(当时我没有意识到文档自相矛盾)。
I believe that the current iOS 4.0 behavior will be the future behavior I prefer the following solution:
我相信当前的 iOS 4.0 行为将是未来的行为我更喜欢以下解决方案:
- Do not implement
applicationDidFinishLaunching:
. - Implement
application:didFinishLaunchingWithOptions:
and check the URL, return YES if you can open it, otherwise NO, but do not open it. If we are on 3.2, open the URL. - Implement
application:handleOpenURL:
and open the URL, return YES if successful, otherwise NO.
- 不执行
applicationDidFinishLaunching:
。 - 实现
application:didFinishLaunchingWithOptions:
并检查URL,如果可以打开则返回YES,否则返回NO,但不要打开它。如果我们使用 3.2,请打开 URL。 - 实现
application:handleOpenURL:
并打开URL,成功则返回YES,否则返回NO。
So in summary, I implement the iOS 4 behavior and added the following line to application:didFinishLaunchingWithOptions:
所以总而言之,我实现了 iOS 4 行为并将以下行添加到 application:didFinishLaunchingWithOptions:
if([[[UIDevice currentDevice] systemVersion] hasPrefix:@"3.2"]) {
[self application:application handleOpenURL:url];
}
which make the code work under 3.2.
这使代码在 3.2 下工作。
回答by powertoold
application:handleOpenURL:
is now DEPRECATED.
application:handleOpenURL:
现在已弃用。
As of iOS 4.2, you can use this for opening URLs:
从 iOS 4.2 开始,您可以使用它来打开 URL:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
Documentation:
文档:
回答by Hitesh Savaliya
I started writing application which used Dropbox api. To understand concept, I ran a sample application using my Key/secret mentioned at dropbox/developer documentation. Once sample app started working, I used same key/secret values for my application.
我开始编写使用 Dropbox api 的应用程序。为了理解概念,我使用我在 dropbox/developer documentation 中提到的 Key/secret 运行了一个示例应用程序。示例应用程序开始工作后,我为我的应用程序使用了相同的密钥/秘密值。
For sample app, implementation of handleOpenURL (or openURL on iOS 4.2) gets executed as expected. For some odd reason, it wasn't the case for my app. My app entered background in order to show login screen and authentication page of dropbox. After successful login and authentication, my app never entered foreground. It was true for both platform Simulator and device (iPad)
对于示例应用程序,handleOpenURL(或 iOS 4.2 上的 openURL)的实现按预期执行。出于某种奇怪的原因,我的应用程序并非如此。我的应用程序进入后台以显示 Dropbox 的登录屏幕和身份验证页面。成功登录和身份验证后,我的应用程序从未进入前台。平台模拟器和设备(iPad)都是如此
I tried almost everything listed on internet including this post. Thanks. There was NO success, though.
我几乎尝试了互联网上列出的所有内容,包括这篇文章。谢谢。但是没有成功。
At last, it STARTEDworking for my application when I did following:
最后,当我执行以下操作时,它开始为我的应用程序工作:
- On simulator, select "iOS Simulator --> Reset Content and Settings", and reset.
- On device, I deleted sample application related executable and which in turn delete cache associated to it.
- 在模拟器上,选择“iOS Simulator --> Reset Content and Settings”,然后重置。
- 在设备上,我删除了与示例应用程序相关的可执行文件,进而删除了与其关联的缓存。
回答by Steve
Add the following to the end of application:DidFinishLaunchingWithOptions
:
将以下内容添加到末尾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;
}
where mvc is my main ViewController, and nc my navigation controller.
其中 mvc 是我的主 ViewController,nc 是我的导航控制器。
Then in the MainViewController, do something like this:
然后在 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];
...
}
after declaring handleOpenURL in the .h of course.
当然,在 .h 中声明 handleOpenURL 之后。
Thanks goes to Christian for putting in the effort for this.
感谢 Christian 为此付出的努力。