【问题标题】:Accessing extensionContext from a presented view controller从呈现的视图控制器访问 extensionContext
【发布时间】:2014-08-28 09:07:07
【问题描述】:

我尝试为共享扩展创建自定义视图控制器。

当我在MainInterface.storyboard 上设置的初始视图控制器之上显示另一个视图控制器时,会发生令人困惑的情况。这个呈现的视图控制器嵌入在导航控制器中(它是它的根视图控制器)。

我检查了presentingViewController

(lldb) po [self presentingViewController]

<_UIViewServiceViewControllerOperator: 0x7a978000>

(lldb) po [[self presentingViewController] extensionContext]

nil

因此,此时扩展上下文为零。我可以通过将 extensionContext 从presentingViewController 传递到presentingViewController 来访问它。

但是,我发现这种行为有点奇怪。应用扩展是否设计为只能从一级视图控制器层次结构访问?

【问题讨论】:

    标签: ios ios8 ios-app-extension


    【解决方案1】:

    如果您要在扩展情节提要中使用多个视图控制器,则必须将对原始视图控制器的 extensionContext 的引用传递给最终负责完成的视图控制器扩展的请求。在初始视图控制器中:

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        let destination = segue.destinationViewController as! FinalViewController
        destination.originalExtensionContext = self.extensionContext
    }
    

    在你的最终视图控制器中:

    @IBAction func dismissController(sender: UIButton!) {
        dismissViewControllerAnimated(true) { () -> Void in
            self.originalExtensionContext.completeRequestReturningItems(self.originalExtensionContext.inputItems, completionHandler: nil)
    }
    

    请注意,您必须为原始扩展上下文创建一个唯一命名的属性,因为extensionContext 已经作为属性名称存在于超类UIViewController 上。您不能将现有的 extensionContext 传递给 UIViewController 的属性 extensionContext,因为它是只读属性。

    【讨论】:

    • 是的,我认为这是传递扩展上下文的最明显方式。我在询问 SDK 中 extensionContext 属性的行为。
    • 据我所知(我现在已经使用过几次这种模式),如果您传递对extensionContext 的引用,则不会出现异常行为。你只需要确保你做的最后一件事是调用completeRequestReturningItems:,因为这将释放扩展上下文,并且在此之后在扩展中调用的任何东西都不会做任何事情。
    【解决方案2】:

    视图控制器呈现的视图控制器使用父级扩展应该没有问题。查看文档:

    The view controller can check this property to see if it participates in an extension request. If no extension context is set for the current view controller, the system walks up the view controller hierarchy to find a parent view controller that has a non nil extensionContext value.

    因此,如果你可以确定你的根视图控制器确实有一个extensionContext,那么这个视图控制器提供的任何视图控制器都应该可以访问它,只需通过它自己的extensionContext 属性。

    注意:如果这不是您观察到的行为,这可能是 SDK 的错误,我建议您提交雷达。

    【讨论】:

    • 如果视图控制器有一个具有extensionContext的父级,它的行为是正确的,但是当它是一个不包含在父子关系中的presentedViewController时,它的行为就不同了。
    • @JesseArmand 是正确的。任何以模态方式呈现的视图都不会包含它正在呈现的视图控制器 extensionContext。
    【解决方案3】:

    虽然这不是清洁代码和架构的最佳方法,但它非常方便:

    在存在extensionContext 的根扩展控制器中:

    final class ShareRootViewController: UIViewController {
        override func viewDidLoad() {
            super.viewDidLoad()
            NSExtensionContext.shared = self.extensionContext
        }
    }
    
    extension NSExtensionContext {
        fileprivate(set) static var shared: NSExtensionContext!
    }
    

    在任何其他视图控制器中:

    let context = NSExtensionContext.shared
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多