简体   繁体   English

从Today扩展中打开特定的ViewController

[英]Opening specific ViewController from Today Extension

I have got two buttons on my today extension. 今天的扩展程序上有两个按钮。 One is dedicated to open MainViewController and the second one need to navigate to second ViewController. 一个专用于打开MainViewController,第二个需要导航至第二个ViewController。

So I made a appURL: 所以我做了一个appURL:

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

and then on a first button I call: 然后在第一个按钮上调用:

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

Which opens app on MainViewController. 这将在MainViewController上打开应用。

How can I open MainViewController and performSegue to my SecondViewController when tapping second button on Today Widget? 轻按“今日”小部件上的第二个按钮时,如何打开MainViewController并对SecondViewController进行performSegue?

I made a second URL scheme for that specific ViewController. 我为该特定ViewController设置了第二个URL方案。 I saw in other simmilar topics that it can be done by calling: 我在其他类似主题中看到可以通过调用来完成:

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

in AppDelegate but don't have any idea how to use it. 在AppDelegate中,但不知道如何使用它。

Use one URL scheme. 使用一种URL方案。 You can add different paths or arguments for different task. 您可以为不同的任务添加不同的路径或参数。

For example, I've an app that displays multiple items in a today extension. 例如,我有一个应用程序,可以在“今日”扩展程序中显示多个项目。 If you tap an item the app is opened. 如果点击某个项目,则将打开该应用程序。

- (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];
    }
}

As you've already mentioned in you question, you need to implement - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options 正如您在问题中已经提到的那样,您需要实现- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options

In my case it more or less looks like this: 就我而言,它或多或少看起来像这样:

- (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;
}

As you can see, I first check, if the url scheme. 如您所见,我首先检查是否为url方案。 If it's the one I expect, I check the path. 如果这是我所期望的,我会检查路径。 By using different paths I'm able to implement different commands the today extension is able to execute . 通过使用不同的路径,我能够实现不同的命令 ,今天的扩展能够执行 Each command may have different arguments. 每个命令可以具有不同的参数。 In case of the "open_item" command, I expect the parameter "itemID". 如果使用“ open_item”命令,则需要参数“ itemID”。

By returning YES, you tell iOS you were able to handle the URL your app was called with. 通过返回YES,您告诉iOS您能够处理调用您的应用程序的URL。

In my app [self _gotoItemWithID:itemID completionHandler:nil] does all the need tasks to display the item. 在我的应用程序[self _gotoItemWithID:itemID completionHandler:nil]执行了所有需要的任务以显示项目。 In your case you would need a function to display the second view controller. 在您的情况下,您需要一个函数来显示第二个视图控制器。

Edit: 编辑:

I forgot to mention that queryDictionary is a method in an NSString extension. 我忘了提到queryDictionary是NSString扩展中的方法。 It takes a string ( self ) and tries to extract URL parameter and return them as dictionary. 它需要一个字符串( 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];
}

I found the solution. 我找到了解决方案。 The answer is deep linking. 答案是深层链接。 Here is my method in appDelegate: 这是我在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

And in the TodayExtensionViewController I defined two URL schemes with same host but different URL paths. 在TodayExtensionViewController中,我定义了两个URL方案,它们具有相同的主机,但URL路径不同。 And made a simple: 并做了一个简单的:

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

for first button but changed the urlPath for the second button. 对于第一个按钮,但更改了第二个按钮的urlPath。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 从iOS 8 Today Extension中的Storyboard加载特定的ViewController - Load specific ViewController from Storyboard in iOS 8 Today Extension 当主应用程序未打开时,Swift 如何从今天的扩展中打开特定的视图控制器 - Swift how to open specific viewcontroller from today extension when main app is not open iOS 5从AppDelegate打开特定的ViewController - IOS 5 Opening a specific ViewController from the AppDelegate 点击扩展程序(今天的扩展程序)后是否可以打开特定的viewcontroller(包含应用程序)? - is it possible to open specific viewcontroller(containing app) after tap on extension(today extension)? 从侧面菜单中选择项目时打开特定的ViewController? - Opening specific ViewController when selecting item from side menu? 从今日扩展(小部件)在主机应用程序中执行操作,无需打开应用程序ios - Perform action in host app from Today extension(Widget) Without opening app ios 在应用程序中的Today扩展和ViewController之间公开类 - make public class between Today extension and ViewController in app 弹出本地通知后打开特定的viewcontroller - Opening a specific viewcontroller after popping local notification 来自Today Extension的打开网址 - Open url from Today Extension 打开通知后从AppDelegate重新加载ViewController - Reload ViewController from AppDelegate after opening a Notification
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM