не может вызвать continueUserActivity в Swift 3/iOS 10

Примечание. Я понял большую часть этого — см. обновление в конце. Еще какое-то замешательство.

Я пытаюсь реализовать обработку NSUserActivity в Xc8b6 под Swift 3, и у меня возникают проблемы с подписью метода для метода протокола обработчика.

В текущем документе этот метод называется:

func application(_ application: UIApplication, 
                 continue userActivity: NSUserActivity, 
       restorationHandler: @escaping ([Any]?) -> Void) -> Bool

Это лишь немного отличается от того, что я вижу в интерфейсе быстрого заголовка. Там тип возвращаемого значения в restoreHandler — Swift.Void.

Когда я пытаюсь это сделать, я получаю сообщение об ошибке:

Метод Objective-C 'application:continue:restorationHandler:', предоставленный методом 'application(_:continue:restorationHandler:)', не соответствует селектору требования ('application:continueUserActivity:restorationHandler:')

Я понимаю, что предупреждения компилятора сейчас не очень хороши, но я понимаю, что для этого найдена сигнатура метода Obj-C, но почему-то мои аргументы не совсем совпадают.

Я не уверен, куда еще пойти с этим. Он соответствует тому, что есть, но что-то не так. Случайное угадывание и проверка мне пока не помогли.

Интересно, что автозаполнение дает мне другую сигнатуру метода:

public func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: ([Any]?) -> Void) -> Bool

Самое приятное в этом то, что он компилируется. Менее приятно то, что он не срабатывает, когда я выбираю проиндексированный элемент из Spotlight и касаюсь его, чтобы запустить приложение.

Очевидно, что мой NSUserAction правильно определил приложение и запустил его. Есть ли что-то, что я мог бы упустить здесь, где он не запускал бы restoreHandler? Обратите внимание, что это преобразовано из проекта, который отлично работал под iOS 9.

Я также видел еще одну версию сигнатуры метода протокола в видеоролике WWDC «Что нового в поиске». Я попробовал это, и он скомпилировался, но не сработал.

В завершение скажу, что это подпись, которую я получил после завершения работы инструмента преобразования Swift 3. Он скомпилировался, но не сработал при запуске из Spotlight:

func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]) -> Void) -> Bool

----Обновлять-----

В порядке. Таким образом, первая сигнатура метода, упомянутая выше, является правильной. Проблема в том, что я определял это в расширении AppDelegate. Это отлично работало в Swift 2.x.

Я поднял его, и все в порядке. Но я хотел бы лучше понять, почему я получаю эти ошибки компиляции при реализации метода протокола из расширения. Это больше не соответствует протоколу? Если я попытаюсь добавить его в расширение, я получу сообщение об ошибке, указывающее, что это дубликат, поэтому я не думаю, что это совсем так.


person jeffro37    schedule 03.09.2016    source источник
comment
Добавление функции в расширение протокола эквивалентно добавлению функции в исходное определение протокола. Вот почему вы получаете ошибку, что это дубликат. Если расширение протокола предназначено только для определенного типа, то это другая история.   -  person user1046037    schedule 03.09.2016
comment
Это не было расширением протокола. Вероятно, мне следует просто создать новый вопрос, потому что на мой старый был дан ответ, и теперь у меня есть новый. Кратко — расширение просто: extension AppDelegate { Так я расширяю класс, но не протокол.   -  person jeffro37    schedule 03.09.2016


Ответы (2)


Первоначальный вопрос был о том, почему continueUserActivity не вызывался (и какова была правильная подпись), поэтому я отвечу на него здесь, добавив некоторую ясность в отношении того, что пошло не так.

Правильная подпись - это то, что я поставил вверху своего поста:

func application(_ application: UIApplication, 
                 continue userActivity: NSUserActivity, 
       restorationHandler: @escaping ([Any]?) -> Void) -> Bool

Имейте в виду, что эта подпись ОТЛИЧАЕТСЯ от того, что обеспечивает автозаполнение в Xc8b6, поэтому я подозреваю, что кто-то другой может воспользоваться этим и извлечь выгоду из этого ответа.

Моя первоначальная проблема заключалась в том, что он не компилировался, потому что я делал это из расширения. Для ясности:

extension AppDelegate {
  func application(_ application: UIApplication,
                   continue userActivity: NSUserActivity,
                   restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
    return true
  }
}

Это работало в любом старом проекте iOS 9/Swift 2.x (со старой подписью continueUserActivity). Я до сих пор не уверен, почему, но он не будет компилироваться в расширение в Xc8/Swift 3.

Я переместил его в область класса, и теперь он отлично работает.

person jeffro37    schedule 03.09.2016
comment
У меня возникла та же проблема с любым дополнительным методом AppDelegate. Они больше не встраиваются в расширения. Это очень раздражает и делает AppDelegate очень грязным. Я думаю, может быть, у func есть такая область, как fileprivate? поэтому расширения их не видят - person Marco Pappalardo; 04.10.2016
comment
@ jeffro37 Ваша подпись выдает мне ошибки. Использование Свифт 4. - person Jonny; 28.11.2017

Итак, похоже, что начиная со Swift 3 методы протокола доступны только в той области видимости, где протокол привязан к классу.

это означает, что все методы AppDelegate внутри протокола UIApplicationDelegate доступны только в классе AppDelegate или в расширении AppDelegate, которое соответствует UIApplicationDelegate.

Если вы попытаетесь получить доступ к методу UIApplicationDelegate за пределами этого класса/расширения, который соответствует UIApplicationDelegate, вы не сможете скомпилировать.

person Marco Pappalardo    schedule 04.10.2016