从Today Extension

时间:2017-10-21 07:15:13

标签: ios swift plist url-scheme

我今天的扩展程序上有两个按钮。一个专用于打开MainViewController,第二个需要导航到第二个ViewController。

所以我做了一个appURL:

   let appURL = NSURL(string: "StarterApplication://")

然后在我打电话的第一个按钮上:

       self.extensionContext?.open(appURL! as URL, completionHandler:nil)

在MainViewController上打开应用程序。

当点击Today Widget上的第二个按钮时,如何打开MainViewController并对我的SecondViewController执行Severn?

我为该特定的ViewController制作了第二个URL方案。我在其他类似的主题中看到,可以通过调用:

来完成
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
}

在AppDelegate中,但不知道如何使用它。

2 个答案:

答案 0 :(得分:1)

使用一个URL方案。您可以为不同的任务添加不同的路径或参数。

例如,我的应用在今天的扩展程序中显示多个项目。如果您点按某个项目,该应用就会被打开。

- (void)_openItem:(SPItem *)item
{
    NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:@"myapp://localhost/open_item?itemID=%@", item.itemID]];
    if (url != nil)
    {
        [self.extensionContext openURL:url completionHandler:nil];
    }
}

正如您在问题中已经提到的那样,您需要实施- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options

就我而言,它或多或少看起来像这样:

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options
{
    BOOL ret;
    if ([url.scheme isEqualToString:@"myapp"])
    {
        if ([url.path isEqual:@"open_item"])
        {
            @try
            {
                NSDictionary *query = [url.query queryDictionary];
                NSString* itemID = query[@"itemID"];
                [self _gotoItemWithID:itemID completionHandler:nil];
            }
            @catch (NSException *exception) {
            }
            ret = YES;
        }
    }
    else
    {
        ret = NO;
    }
    return ret;
}

如您所见,我首先检查一下,如果网址方案。如果它是我期望的那个,我检查路径。通过使用不同的路径,我能够实现不同的命令,今天的扩展能够执行。每个命令可能有不同的参数。如果是&#34; open_item&#34;命令,我希望参数&#34; itemID&#34;。

通过返回YES,您告诉iOS您能够处理调用应用程序的URL。

在我的应用[self _gotoItemWithID:itemID completionHandler:nil]中执行显示项目的所有需要​​任务。在您的情况下,您需要一个功能来显示第二个视图控制器。

修改

我忘了提到queryDictionary是NSString扩展中的方法。它需要一个字符串(self)并尝试提取URL参数并将它们作为字典返回。

- (NSDictionary*)queryDictionary
{
    NSCharacterSet* delimiterSet = [NSCharacterSet characterSetWithCharactersInString:@"&;"];
    NSMutableDictionary* pairs = [NSMutableDictionary dictionary];
    NSScanner* scanner = [[NSScanner alloc] initWithString:self];
    while (![scanner isAtEnd])
    {
        NSString* pairString;
        [scanner scanUpToCharactersFromSet:delimiterSet
                                intoString:&pairString] ;
        [scanner scanCharactersFromSet:delimiterSet intoString:NULL];
        NSArray* kvPair = [pairString componentsSeparatedByString:@"="];
        if ([kvPair count] == 2)
        {
            NSString* key = [[kvPair objectAtIndex:0] stringByRemovingPercentEncoding];
            NSString* value = [[kvPair objectAtIndex:1] stringByRemovingPercentEncoding];
            [pairs setObject:value forKey:key] ;
        }
    }
    return [NSDictionary dictionaryWithDictionary:pairs];
}

答案 1 :(得分:1)

我找到了解决方案。答案是深层次的联系。这是我在appDelegate中的方法:

    func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {


    let urlPath : String = url.path as String!
    let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)

    if(urlPath == "/Action"){

        let ActionView: ActionViewController = mainStoryboard.instantiateViewController(withIdentifier: "ActionViewController") as! ActionViewController
        self.window?.rootViewController = ActionView
    } else if(urlPath == "/VoiceCommandView") {

        let VoiceCommandView: ViewController = mainStoryboard.instantiateViewController(withIdentifier: "ViewController") as! ViewController
        self.window?.rootViewController = VoiceCommandView

    }
    self.window?.makeKeyAndVisible()

    return true

在TodayExtensionViewController中,我定义了两个具有相同主机但URL路径不同的URL方案。并且做了一个简单的:

        self.extensionContext?.open(startAppURL! as URL, completionHandler:nil)

表示第一个按钮,但更改了第二个按钮的urlPath。