Жесткое кодирование NSUserActivityTypes для восстановления различных моделей данных

Начиная с iOS 13 Apple рекомендует сохранять состояние пользователя с помощью объекта NSUserActivity, прикрепленного к сцена, поэтому я пытался а) лучше понять, как работает NSUserActivity и б) реализовать это в своем собственном коде. Работая с документацией Apple, я наткнулся на этот фрагмент кода:

        class var activityType: String {
        let activityType = ""

        // Load our activity type from our Info.plist.
        if let activityTypes = Bundle.main.infoDictionary?["NSUserActivityTypes"] {
            if let activityArray = activityTypes as? [String] {
                return activityArray[0]
            }
        }

        return activityType
    }

Я понимаю, что это делает (он просматривает файл Info.plist для записи с именем "NSUserActivityTypes", если он существует, он пытается получить связанный массив типов активности, а затем читает первый элемент в массиве), но я не понимаю, почему. В частности, я не понимаю, почему мы читаем только первый элемент в activityArray. В этом случае мы знаем, что первым (и единственным элементом) является «com.apple.apple-samplecode.StateRestoration.activity», потому что мы должны вручную создать эту запись plist. Но я не понимаю, почему мы жестко кодируем, просматривая первый элемент массива, чтобы получить тип активности, потому что, если мы знаем, что просто вернём строку "com.apple.apple-samplecode. StateRestoration.activity", почему бы просто не написать такой код:

class var activityType: String {
       return "com.apple.apple-samplecode.StateRestoration.activity"
    }

Я никогда раньше не работал с NSUserActivity, и я понимаю, что его можно (обычно используют?) использовать для других целей, кроме сохранения/восстановления состояния, поэтому может быть много различных видов действий пользователя, которые может поддерживать ваше приложение (передача обслуживания, интеграция Siri , так далее.). Поэтому я бы предположил, что мы хотим, чтобы наш код был максимально надежным, чтобы не делать никаких предположений о типах объектов NSUserActivity, которые мы можем получить.

Может быть, кто-то, у кого больше опыта работы с NSUserActivity, может помочь объяснить, каким образом NSUserActivity может быть передан моему приложению, и почему мы можем жестко закодировать первый элемент массива, в то время как в других местах мы хотим проверить, не передается ли активность — это правильный вид деятельности (хотя мы знаем, что наш набор поддерживаемых действий имеет только один вид деятельности, поэтому, по-видимому, в первую очередь мы получим только один вид деятельности?).

Кроме того, это не уникально для примера кода Apple... эта запись в блоге также использует аналогичный подход при чтении файла Info.plist:

extension Bundle {
    var activityType: String {
        return Bundle.main.infoDictionary?["NSUserActivityTypes"].flatMap { ($0 as? [String])?.first } ?? ""
    }
}

person RyanBDevilled    schedule 19.01.2020    source источник


Ответы (2)


Я думаю, что оба примера кода — просто фиктивные способы объяснить, как работают состояния. Там они используют один идентификатор восстановления (com.apple.apple-samplecode.StateRestoration.activity), но ваше приложение может иметь больше, поэтому, как вы говорите, пример кода больше не имеет смысла.

Также обратите внимание, что даже при использовании одного идентификатора восстановления у вас есть все поля NSUserActivity (включая userInfo), которые помогут вам различать состояния. Конечно, было бы грязно иметь очень разные состояния, использующие один и тот же идентификатор восстановления.

person Rivera    schedule 27.04.2020

У меня есть такое же сомнение, когда я читаю пример Apple восстановления состояния пользователя с помощью NSUserActivity, потому что в моем прошлом проекте у меня всегда был Constant.swift для обработки всей строки жесткого кода (что-то вроде идентификатора или ключа), например:

Константы.swift

struct Constants {
    static let userActivityTypeA = "com.apple.apple-samplecode.StateRestoration.activityA"
    static let userActivityTypeB = "com.apple.apple-samplecode.StateRestoration.activityB"
}

Я понимаю, что это делает (он просматривает файл Info.plist для записи с именем NSUserActivityTypes, если он существует, он пытается получить связанный массив ActivityTypes, а затем читает первый элемент в массиве), но что я не знаю не понимаю, почему.

На мой взгляд, не обязательно следовать примеру Apple (добавление типа активности в info.plist и чтение его с помощью Bundle.main.infoDictionary). Apple просто предоставляет способ, который является более чистым и может быть легко идентифицирован, что представляет собой эта строка, предоставляя фиксированный ключ NSUserActivityTypes в info.plist.

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

почему мы можем жестко запрограммировать первый элемент массива, в то время как в других местах мы хотим проверить, является ли переданное действие правильным видом действия (хотя мы знаем, что наш массив поддерживаемых действий имеет только один вид действия, так что, по-видимому, мы получим только один вид активности?).

Это действительно зависит от того, сколько ActivityType поддерживают ваши приложения, например, вы можете добавить еще несколько типов в будущем, например, тип A перейдет к ViewController A, а тип B откроет браузеры In-App в ваших приложениях. Если вы знаете, что ваши приложения поддерживают только один вид активности, да, вам даже не нужно его проверять, но в целом мы всегда хотим подтвердить полученное и дать соответствующий ответ.

person paky    schedule 04.11.2020