【问题标题】:How to launch a parent iOS App from its App Extension如何从其应用扩展启动父 iOS 应用
【发布时间】:2014-09-08 15:12:24
【问题描述】:

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

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

【问题讨论】:

    标签: ios ios-app-extension today-extension share-extension


    【解决方案1】:

    在 WWDC 会话 Creating Extensions for iOS and OS X, Part 1 大约 22 分钟标记处,说要使用 UIViewController 的 extensionContext 中的 openURL:completionHandler: 方法打开 custom URL scheme

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

    【讨论】:

    • 这不起作用。从 Apple 的文档中,我读到一件事,他们说上述开放 URL 不适用于某些应用程序扩展。那么,我可以尝试其他任何方法吗?。
    • 它绝对适用于 Today Extensions - 我在 github 上有一个示例:github.com/kmonaghan/CBPExtensionExample
    • 除了今天的扩展,如操作扩展或文件提供程序扩展?。请确认
    • 尝试从键盘执行此操作,但不起作用。
    • 最简单实用的答案
    【解决方案2】:

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

    您需要为您的主机应用创建自己的 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
    }
    

    【讨论】:

    • PLzz 告诉如何通过扩展调用它,因为这似乎不完整的答案
    • 真的没有什么特别的。就我而言,我有一个仅包含一个 ViewController 的共享扩展。我将openURL 放在那个ViewController 中,并在viewDidAppear 之后调用了self.openURL(URL(string: "myapp://com.mydomain.share?urlparams")!)。 ViewController 本身几乎是空的——我只是收集传入的文件并将它们保存到本地文件夹中,然后再进行上述调用。不要忘记注册您的 URL 方案 myapp...
    【解决方案3】:

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

    1- 在父应用 plist 中添加自定义 URL,例如

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

    希望能正常运行,也可以在扩展应用和父应用之间共享数据

    【讨论】:

    • 由于某种原因,它会启动应用程序并在没有第 4 步的情况下运行。此外,AppDelegate 方法 func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Boolfunc application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool 均未触发。
    • 当您需要打开其他vc而不是inittail vc时,将使用第4步
    • 是否有理由将URL Type 添加到Info.plist,而不是通过项目设置-> 主机目标-> 信息选项卡-> 添加 URL 类型,@Awais?
    【解决方案4】:

    我在这里问了一个类似的问题:Communicating with/opening Containing app from Share extension。基本上,你可以做几件事。

    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 中,如果您的扩展在后台任务完成时没有运行,系统会在后台启动您的包含应用程序并调用应用程序:handleEventsForBackgroundURLSession :completionHandler: 应用委托方法。

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

    【讨论】:

    • 但是苹果会推荐这种方式吗?请确认
    • @loganathan 不太确定,但我个人认为它足够干净,Apple 会让它滑动(尤其是基于他们进入应用商店的一些东西)。
    • FWIW:我使用了这种方法,并且它确实在 iOS 8.0 中有效,但是从那时到现在(可能是 9.0,可能更早)之间的某个时间点,它停止了工作:(
    【解决方案5】:

    文档非常清楚地说明您可以在 Today 扩展中使用 extensionContext openURL。暗示,openURL 只能在 Today 异常中使用,我们的经验证明这是正确的——我也无法在 Share 扩展中使用它。

    我很想知道 Apple 的审核流程是否接受这些变通方法。我对此表示怀疑。如果 Apple 想让它工作,他们会很容易地允许它。

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

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

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

    【讨论】:

      【解决方案6】:

      这是另一种方法:

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

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

      考虑使用本地通知来唤醒主机应用,而不是这样。

      【讨论】:

      • UIApplication.shared.open(URL(string:"openPdf://")!) 而不是 UIApplication.shared.openURL(URL(string:"openPdf://")!)跨度>
      • 它有效!不再需要遇到响应者
      【解决方案7】:

      这是工作解决方案(在 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)
          }
      
      }
      

      【讨论】:

        【解决方案8】:

        这是 ios 14 和 xcode 13 的Valentin Shergin's 解决方案

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-03-07
          • 1970-01-01
          • 1970-01-01
          • 2015-10-07
          • 2018-10-14
          • 1970-01-01
          • 2015-07-01
          相关资源
          最近更新 更多