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

问题描述 投票:0回答:10

有人知道如何从应用程序扩展的视图控制器启动父应用程序吗?

我只想从应用程序扩展启动主应用程序。

ios ios-app-extension today-extension share-extension
10个回答
13
投票

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

您需要为您的主机应用程序创建自己的 URL 方案,然后将此函数添加到您的 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
}

12
投票

在 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];

12
投票

它正在我当前的工作应用程序中使用操作扩展

1-在父应用程序 plist 中添加自定义 URL,例如 enter image description here

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-在按钮操作中或您想做的地方调用此函数

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

这里 homevc 是应该显示的视图控制器的类名

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

我希望能正常工作,还可以在扩展应用程序和父应用程序之间共享数据


3
投票

这是

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)
        }
}

2
投票

我在这里问了类似的问题:与共享扩展程序通信/打开包含应用程序。基本上,您可以做几件事。

  1. 使用 UIWebView 的 loadRequest webView 加载包含应用程序 URL 的 NSURL 请求。例如,

    NSURL *url = [NSURL URLWithString:@"myurl"];
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
    [self.webView loadRequest:request];
    
  2. 使用 UIDocumentInteractionController 和自定义文件扩展类型来提供指向您的包含应用程序的链接(并且仅包含您的包含应用程序)

  3. 启动“假”NSURL 会话以获得以下功能:在 iOS 中,如果后台任务完成时您的扩展程序未运行,系统会在后台启动您的包含应用程序并调用 application:handleEventsForBackgroundURLSession:completionHandler: app委托方法。

第一个可能是您最好的选择。


2
投票

文档非常清楚地说明您可以在 Today 扩展中使用 extensionContext openURL。 言外之意,openURL 只能在 Today 例外中使用,我们的经验证明这是真的——我也无法在共享扩展中使用它。

我有兴趣了解 Apple 的审核流程是否接受这些变通办法。 我对此表示怀疑。 如果苹果希望它发挥作用,他们很容易允许它。

Apple 允许任何 Today 小部件使用 openURL:completionHandler: 打开小部件自己的包含应用程序的方法。

如果您使用此方法从“今日”小部件打开其他应用程序, 您提交的 App Store 可能需要额外审核以确保 符合今日小部件的意图。

我确定第二段是在 Launcher 被接受、拒绝然后批准销售之后添加的。


2
投票

这是工作解决方案(在 iOS 9.2 上测试)至少适用于键盘扩展。该类别添加了特殊方法来访问隐藏的

sharedApplication
对象,然后对其调用
openURL:
。 (当然,那么你必须在你的应用程序方案中使用
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)
    }

}

2
投票

这是另一种方法:

  1. 从这里开始第 1 步
  2. 选择扩展目标并转到其
    Build Settings
    。将
    Require Only App-Extension Safe API
    设置为
    NO
  3. 使用
    UIApplication.shared.openURL(URL(string:"openPdf://")!)
    就像您通常在扩展程序之外打开网址一样。

请注意,您将收到 “openURL”在 iOS 10.0 中已弃用警告。所以这看起来并不能保证它将来会起作用。

考虑使用本地通知来唤醒主机应用程序而不是这个。


1
投票

我在扩展程序中使用此代码通过自定义方案 url 打开主应用程序:

fileprivate func openUrl(url: URL?) {
    let selector = sel_registerName("openURL:")
    var responder = self as UIResponder?
    while let r = responder, !r.responds(to: selector) {
        responder = r.next
    }
    _ = responder?.perform(selector, with: url)
}

在调用此函数之前,请确保扩展程序有足够的时间来加载。


0
投票

在 Xcode-16.1、iOS-18 中测试。
转到父应用程序的目标 -> 信息。 向下滚动并添加 URL 类型 info.plist

在这里,标识符应该是您的父应用程序的包标识符。

现在添加以下代码以从应用程序扩展

打开父应用程序
func openParentApp() {
    if let url = URL(string: "openmybestappfromkeyboard://") {
        var responder: UIResponder? = self
        while responder != nil {
            if let application = responder as? UIApplication {
                application.open(url)
                break
            }
            responder = responder?.next
        }
    }
}

现在,转到父应用程序的 AppDelegate 并添加以下代码。

func application(_ application: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
   if url.scheme == "openmybestappfromkeyboard" {
       return true
   } else {
       return false
   }
}
© www.soinside.com 2019 - 2024. All rights reserved.