简体   繁体   English

如何从其应用程序扩展启动父 iOS 应用程序

[英]How to launch a parent iOS App from its App Extension

Does any one know how to launch the parent app from the app extension's view controller?有谁知道如何从应用程序扩展的视图 controller 启动父应用程序?

I just want to launch the main app from its app extension.我只想从其应用程序扩展启动主应用程序。

In the WWDC session Creating Extensions for iOS and OS X, Part 1 around the 22 minute mark the say to use the openURL:completionHandler: method from the UIViewController's extensionContext to open a custom URL scheme在 WWDC 会话为 iOS 和 OS X 创建扩展中,第 1 部分大约 22 分钟标记了使用 UIViewController 的extensionContext 中openURL:completionHandler:方法打开自定义 URL 方案的说明

[self.extensionContext openURL:[NSURL URLWithString:@"your-app-custom-url-scheme://your-internal-url"]
             completionHandler:nil];

Working solution in Swift 3.1 (tested in iOS10): Swift 3.1 中的工作解决方案(在 iOS10 中测试):

You need to create your own URL Scheme for your host app , then add this function to your ViewController and call it with openURL("myScheme://myIdentifier")您需要为您的主机应用程序创建您自己的 URL Scheme ,然后将此函数添加到您的 ViewController 并使用openURL("myScheme://myIdentifier")调用它

//  Function must be named exactly like this so a selector can be found by the compiler!
//  Anyway - it's another selector in another instance that would be "performed" instead.
func openURL(_ url: URL) -> Bool {
    var responder: UIResponder? = self
    while responder != nil {
        if let application = responder as? UIApplication {
            return application.perform(#selector(openURL(_:)), with: url) != nil
        }
        responder = responder?.next
    }
    return false
}

it is working in my current working app using action extension它使用操作扩展在我当前的工作应用程序中工作

1- in parent app plist add custom URL like 1- 在父应用程序 plist 添加自定义 URL,如在此处输入图片说明

2- add both functions in your extension view controller 2- 在您的扩展视图控制器中添加这两个功能

func openURL(url: NSURL) -> Bool {
    do {
        let application = try self.sharedApplication()
        return application.performSelector(inBackground: "openURL:", with: url) != nil
    }
    catch {
        return false
    }
}

func sharedApplication() throws -> UIApplication {
    var responder: UIResponder? = self
    while responder != nil {
        if let application = responder as? UIApplication {
            return application
        }

        responder = responder?.next
    }

    throw NSError(domain: "UIInputViewController+sharedApplication.swift", code: 1, userInfo: nil)
}

3- call this function in your button action or somewhere you want to do 3- 在你的按钮动作或你想做的地方调用这个函数

self.openURL(url: NSURL(string:"openPdf://HomeVC")!)

here homevc is the class name of your View controller which should be presented这里 homevc 是您的视图控制器的类名,应该显示

4- in your app delegate implement the method like 4-在您的应用程序委托中实现类似的方法

  func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    let urlPath : String = url.absoluteString
    print(urlPath)
    if urlPath.contains("HomeVC"){
        //here go to firstViewController view controller
        self.window = UIWindow(frame: UIScreen.main.bounds)

        let storyboard = UIStoryboard(name: "Main", bundle: nil)

        let initialViewController = storyboard.instantiateViewController(withIdentifier: "homeVC")

        self.window?.rootViewController = initialViewController
        self.window?.makeKeyAndVisible()
    }
}

I hope will work fine, can also share data between extension app and parent app我希望能正常工作,也可以在扩展应用程序和父应用程序之间共享数据

I asked a similar question here: Communicating with/opening Containing app from Share extension .我在这里问了一个类似的问题: Communicating with/opening Containing app from Share extension Basically, you can do a couple things.基本上,你可以做几件事。

  1. Use a UIWebView's loadRequest webView to load an NSURL request with your containing app's url.使用 UIWebView 的 loadRequest webView 加载包含应用程序 url 的 NSURL 请求。 For example,例如,

     NSURL *url = [NSURL URLWithString:@"myurl"]; NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url]; [self.webView loadRequest:request];
  2. Use a UIDocumentInteractionController and a custom file extension type to provide a link to your containing app (and your containing app only)使用 UIDocumentInteractionController 和自定义文件扩展名类型来提供指向包含应用程序的链接(仅限包含应用程序)

  3. Start a "fake" NSURL session to get the following functionality: In iOS, if your extension isn't running when a background task completes, the system launches your containing app in the background and calls the application:handleEventsForBackgroundURLSession:completionHandler: app delegate method.启动“假”NSURL 会话以获取以下功能:在 iOS 中,如果您的扩展程序在后台任务完成时未运行,系统会在后台启动您的包含应用程序并调用 application:handleEventsForBackgroundURLSession:completionHandler: app delegate 方法.

The first one is probably your best bet.第一个可能是你最好的选择。

The documentation is pretty clear on saying that you can use extensionContext openURL within a Today extension.该文档非常清楚地说明您可以在 Today 扩展中使用 extensionContext openURL。 By implication, openURL can only be used in a Today exception and our experiences are proving this to be true--I also can't get it working from within a Share extension.这意味着,openURL 只能在 Today 异常中使用,我们的经验证明这是真的——我也无法在 Share 扩展中使用它。

I would be interested to see if any of these work arounds are accepted by Apple's review process.我很想知道 Apple 的审核流程是否接受了这些变通方法中的任何一个。 I doubt it.我对此表示怀疑。 If Apple wanted it to work, it would have been easy enough for them to allow it.如果苹果想让它工作,他们很容易允许它。

Apple allows any Today widget to use the openURL:completionHandler: method to open the widget's own containing app. Apple 允许任何 Today 小部件使用 openURL:completionHandler: 方法打开小部件自己的包含应用程序。

If you employ this method to open other apps from your Today widget, your App Store submission might entail additional review to ensure compliance with the intent of Today widgets.如果您使用此方法从“今日”小部件打开其他应用程序,则您提交的 App Store 可能需要额外审核以确保符合“今日”小部件的意图。

I'm certain this second paragraph was added after Launcher was accepted, rejected, and then later approved for sale.我确定第二段是在 Launcher 被接受、拒绝,然后被批准出售之后添加的。

Here is another way to do it:这是另一种方法:

  1. Step 1 from here从这里开始的第 1 步
  2. Select extension target and go to its Build Settings .选择扩展目标并转到其Build Settings Set Require Only App-Extension Safe API to NO .Require Only App-Extension Safe APINO
  3. Use UIApplication.shared.openURL(URL(string:"openPdf://")!) as you normally would do it outside extension to open urls.使用UIApplication.shared.openURL(URL(string:"openPdf://")!)就像您通常在扩展程序之外打开网址一样。

Note, that you'll get 'openURL' was deprecated in iOS 10.0 warning .请注意,您将收到'openURL' was deprecated in iOS 10.0 warning So this looks like it is not guaranteed to work in future.所以这看起来不能保证将来会起作用。

Consider using local Notifications to wake up host app instead of this.考虑使用本地通知来唤醒主机应用程序而不是这个。

Here is Valentin Shergin's solution for ios 14 & xcode 13这是Valentin Shergin's针对ios 14 和 xcode 13的解决方案

extension KeyboardViewController{
    func openURL(url: NSURL) -> Bool {
            do {
                let application = try self.sharedApplication()
                return (application.perform("openURL:", with: url) != nil)
            }
            catch {
                return false
            }
        }

        func sharedApplication() throws -> UIApplication {
            var responder: UIResponder? = self
            while responder != nil {
                if let application = responder as? UIApplication {
                    return application
                }

                responder = responder?.next
            }

            throw NSError(domain: "UIInputViewController+sharedApplication.swift", code: 1, userInfo: nil)
        }
}

Here is working solution (tested on iOS 9.2) at least for Keyboard Extension.这是至少适用于键盘扩展的工作解决方案(在 iOS 9.2 上测试) This category adds special method for access to hidden sharedApplication object and then call openURL: on it.该类添加了访问隐藏的sharedApplication对象的特殊方法,然后在其上调用openURL: sharedApplication (Of course then you have to use openURL: method with your app scheme.) (当然,你必须在你的应用程序方案中使用openURL:方法。)

extension UIInputViewController {

    func openURL(url: NSURL) -> Bool {
        do {
            let application = try self.sharedApplication()
            return application.performSelector("openURL:", withObject: url) != nil
        }
        catch {
            return false
        }
    }

    func sharedApplication() throws -> UIApplication {
        var responder: UIResponder? = self
        while responder != nil {
            if let application = responder as? UIApplication {
                return application
            }

            responder = responder?.nextResponder()
        }

        throw NSError(domain: "UIInputViewController+sharedApplication.swift", code: 1, userInfo: nil)
    }

}

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM