今天的应用扩展小部件,点击打开包含应用程序

59
我已经使用这些苹果文档为我的应用程序+Quotes实现了一个今日小部件,它可以在通知中心显示当天的引用。我想实现的目标是,当用户在今天的通知视图中点击+Quotes小部件时,打开包含应用程序+Quotes,就像如果您在今天视图中点击日历一样。我尝试在标签上覆盖一个按钮,当点击它时,它将调用-(void)openURL:(NSURL *)URL completionHandler:(void (^)(BOOL success))completionHandler,然后打开我声明的自定义URL方案以打开包含的应用程序。问题是它没有打开包含的应用程序。

+Quotes Today App Extension Widget

-(IBAction)myButton:(id)sender {
    NSURL *customURL = [NSURL URLWithString:@"PositiveQuotes://"];
    [self openURL:customURL completionHandler:nil];
}
5个回答

63

编辑:好的,这里只需要稍作更正。我已经按照上述建议在标签上放置了一个按钮,并使用以下代码使其工作:

- (IBAction) goToApp: (id)sender { 
    NSURL *url = [NSURL URLWithString:@"floblog://"];
    [self.extensionContext openURL:url completionHandler:nil]; 
  }

我将它链接到了“Touch Up Inside”事件。然而,这也会导致当用户滚动Today视图时应用程序启动。

=======================================

我遇到了相同的问题。但是,由于iOS 8第一个beta版本的发行说明中提到:

已知问题:openURL在扩展中无法工作。

所以我想我们至少得等到beta 2。


3
好的,这里只需要进行一点小的修正。我按照之前提到的建议,将一个按钮放在标签上,并使用以下代码实现了它:
  • (IBAction) goToApp: (id)sender { NSURL *url = [NSURL URLWithString:@"floblog://"]; [self.extensionContext openURL:url completionHandler:nil];
}我将按钮与“Touch Up Inside”事件链接在了一起。不过,这也会导致当用户滚动“今天”视图时应用程序启动。
- sunseeker
没问题。你有想法如何解决我在上句中描述的行为吗? - sunseeker
只有在您滚动并手指仍然放在无形按钮上时才会发生这种情况吗? - CoderNinja
2
值得注意的是,这种方法仅适用于今日扩展。 - BFar
我使用单击手势识别器来处理选项卡,而不是在标签上添加一个空按钮。然后,在选择器中添加以下函数:
  • (void)handleSingleTap:(UITapGestureRecognizer *)recognizer { NSURL *myURL = [NSURL URLWithString:@"AppUrlType://home"]; [self.extensionContext openURL:myURL completionHandler:nil]; }
- Panayot
显示剩余4条评论

52

根据苹果文档,这是Swift 2版本。

extensionContext?.openURL(NSURL(string: "foo://")!, completionHandler: nil)

Swift 3 版本

extensionContext?.open(URL(string: "foo://")! , completionHandler: nil)

别忘记在 Info.plist 中添加自定义URL Scheme

输入图片描述


如何恢复用户活动,例如搜索被点击?我们是否需要在TodayViewController中创建一个NSUserActivity作为小部件被点击的准备(即在openURL调用之前)? - Ace Green
1
以防其他人和我一样傻:此“URL类型”位于主应用程序目标的信息选项卡中,而不是小部件的选项卡中。 - Todd

27

@sunseeker的回答是好的,但它“隐藏”在评论中。而且,由于被接受的答案说这不可能实现,这可能会误导访问者。

此代码有效:

- (IBAction)launchHostingApp:(id)sender
{
  NSURL *pjURL = [NSURL URLWithString:@"hostingapp://home"];
  [self.extensionContext openURL:pjURL completionHandler:nil];
}

我正在使用带有Yosemite Beta 1的Xcode 6.0(6A215l)。

就像苹果在处理常见场景中所说:

扩展不直接告诉其包含的应用程序打开; 相反,它使用NSExtensionContext的openURL:completionHandler:方法来告诉系统打开其包含的应用程序。当扩展使用此方法打开URL时,系统会在满足请求之前对其进行验证。


这个能在模拟器上运行吗?我收到了一个警告,说这个URL不受支持。 - Imran
7
“hostingapp”方案是你必须在Infos.plist中设置的内容。它可以是任何东西。更多细节请参见此处:https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/AdvancedAppTricks/AdvancedAppTricks.html#//apple_ref/doc/uid/TP40007072-CH7-SW50 中的“实施自定义URL方案”小节。 - teriiehina
3
要在你的plist中创建URL方案"hostingapp",请参考https://dev59.com/4msy5IYBdhLWcg3w9Svk @Mike S. - Lito

3

在不添加隐藏按钮的情况下,另一种方法是在UILabel上添加UITapGestureRecognizer(确保将userInteractionEnabled设置为true)。在处理程序中检查识别器状态,以确保达到了UIGestureReconizerStateEnded(而不是Cancelled或Failed),然后运行您的openUrl代码。


3

以防万一,这里附上了使用错误处理版本的Swift 3版本:

let myAppUrl = URL(string: "main-screen:")!
extensionContext?.open(myAppUrl, completionHandler: { (success) in
    if (!success) {
        print("error: failed to open app from Today Extension")
    }
})

为了让其正常工作,您需要打开应用程序的info.plist文件(以源代码方式打开),并在最顶部,在此标签后添加:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>

添加以下内容,这样应用程序就会知道它应该处理哪些URL:
这是如何打开包含应用程序并在应用程序和扩展之间共享用户默认值的完整示例。请参考这里

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接