Доступ к extensionContext из представленного контроллера представления

Я попытался создать собственный контроллер представления для расширения общего доступа.

Запутанная ситуация возникает, когда я представляю другой контроллер представления поверх исходного контроллера представления, который был установлен в MainInterface.storyboard. Этот представленный контроллер представления встроен в контроллер навигации (это его корневой контроллер представления).

Я проверил PresentingViewController

(lldb) po [self presentingViewController]

<_UIViewServiceViewControllerOperator: 0x7a978000>

(lldb) po [[self presentingViewController] extensionContext]

nil

Таким образом, контекст расширения на данный момент равен нулю. Я мог бы получить доступ к extensionContext, передав его из PresentingViewController в PresentingViewController.

Но я нашел это поведение немного странным. Расширение приложения предназначено для доступа только с одного уровня иерархии контроллера представления?


person Jesse Armand    schedule 28.08.2014    source источник


Ответы (3)


Если вы собираетесь использовать более одного контроллера представления в своей раскадровке расширения, вам придется передать ссылку на 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, так как это атрибут только для чтения.

person Michael Frain    schedule 12.11.2015
comment
Да, я понял, что это самый очевидный способ обойти контекст расширения. Я спрашивал о поведении свойства extensionContext в SDK. - person Jesse Armand; 17.11.2015
comment
Насколько я могу судить (и я использовал этот шаблон пару раз), нет ничего необычного в том, если вы передаете ссылку на extensionContext. Вам просто нужно убедиться, что последнее, что вы делаете, это вызов completeRequestReturningItems:, так как это освободит контекст расширения, и все, что вызывается в расширении после этого, ничего не сделает. - person Michael Frain; 17.11.2015

Контроллер представления, представляемый контроллером представления, не должен иметь проблем с использованием родительского расширения. Взглянув на документацию:

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, и я бы рекомендовал зарегистрировать радар.

person Infinity James    schedule 28.08.2014
comment
Он ведет себя правильно, если у контроллера представления есть родитель, у которого есть extensionContext, но он ведет себя иначе, когда это представленный ViewController, который не включен в отношение родитель-потомок. - person Jesse Armand; 03.09.2014
comment
@JesseArmand прав. Любое представление, представленное модально, не будет содержать расширение контекста представления контроллеров представлений. - person dwlz; 21.09.2014

Хотя это не лучший подход для чистого кода и архитектуры, он весьма удобен:

В корневом контроллере расширения, где существует 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
person Alexander Kulabukhov    schedule 15.05.2019