I've tried creating a custom view controller for a share extension.
A confusing situation happens when I present another view controller on top of the initial view controller that was set on the MainInterface.storyboard
. This presented view controller is embedded in a navigation controller (it's the root view controller of it).
I did a check on the presentingViewController
(lldb) po [self presentingViewController]
<_UIViewServiceViewControllerOperator: 0x7a978000>
(lldb) po [[self presentingViewController] extensionContext]
nil
So, the extension context is nil at this point. I could access the extensionContext
by passing it around from the presentingViewController to the presentedViewController.
But, I found this behavior is a bit strange. Is the app extension designed to only be accessed from one level of view controller hierarchy?
If you're going to use more than a single view controller in your extension storyboard, you'll have to pass a reference to the extensionContext
of the original view controller to the view controller that will ultimately be responsible for completing the extension's request. In the initial view controller:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let destination = segue.destinationViewController as! FinalViewController
destination.originalExtensionContext = self.extensionContext
}
And in your final view controller:
@IBAction func dismissController(sender: UIButton!) {
dismissViewControllerAnimated(true) { () -> Void in
self.originalExtensionContext.completeRequestReturningItems(self.originalExtensionContext.inputItems, completionHandler: nil)
}
Note that you have to create a uniquely named property for the original extension context, since extensionContext
already exists as a property name on the superclass UIViewController
. You can't pass the existing extensionContext
to the UIViewController's property extensionContext
as it is a read-only attribute.
The view controller being presented by a view controller should have no problem using the parent's extension. Taking a look at the documentation:
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.
Therefore, if you can be certain of the fact that your root view controller does indeed have an extensionContext
, any view controller presented by this view controller should have access to it, simply through it's own extensionContext
property.
Note: If this is not the behaviour you a re observing, this may be a bug with the SDK, and I would recommend filing a radar.
While it's not the best approach for clean code and architecture, it's quite handy:
In root extension controller where extensionContext
exists:
final class ShareRootViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
NSExtensionContext.shared = self.extensionContext
}
}
extension NSExtensionContext {
fileprivate(set) static var shared: NSExtensionContext!
}
In any other view controller:
let context = NSExtensionContext.shared
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With