Вопрос или проблема
let mainSceneTargetContentIdentifier = "com.apple.gallery.mainIdentifier"
var window: UIWindow?
// MARK: - UIWindowSceneDelegate
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
print("willConnectTo") //3
if let userActivity = connectionOptions.userActivities.first ?? session.stateRestorationActivity {
if !configure(window: window, with: userActivity) {
Swift.debugPrint("Не удалось восстановить из \(userActivity)")
}
}
// Свойство 'window' будет автоматически загружено с начального контроллера представления из storyboard.
// Установите предикаты активации, которые работают с 'targetContentIdentifier'.
let conditions = scene.activationConditions
let prefsPredicate = NSPredicate(format: "self == %@", mainSceneTargetContentIdentifier)
// Главный предикат, который сообщает системе, какой тип контента может отображать сцена.
conditions.canActivateForTargetContentIdentifierPredicate = prefsPredicate
// Вторичный предикат, который сообщает системе, что эта сцена особенно заинтересована в определенном типе контента.
conditions.prefersToActivateForTargetContentIdentifierPredicate = prefsPredicate
}
это из
сессии apple WWDC 2019 212: Введение в несколько окон на iPad
Согласно моему пониманию кода, значение targetContentIdentifier
равно com.apple.gallery.openDetail
, а значение mainSceneTargetContentIdentifier
равно com.apple.gallery.mainIdentifier
, поэтому при сравнении targetContentIdentifier
и mainSceneTargetContentIdentifier
в NSPredicate(format: "self == %@", mainSceneTargetContentIdentifier)
возвращается false, потому что, очевидно, две строки не совпадают. Тем не менее, сцена активируется несмотря ни на что. Для целей тестирования я инициализировал NSPredicated(value:false)
и присвоил его условиям сцены, и сцена была активирована.
Может кто-то объяснить, почему? Согласно документации, это должно работать, если NSPredicate возвращает true, а не наоборот.
Ответ или решение
Причины, по которым ваша сцена активируется, даже когда canActivateForTargetContentIdentifierPredicate
возвращает false
, могут быть связаны с несколькими аспектами механизма активации сцен в iOS. Давайте разберемся в этом вопросе подробнее.
-
Понимание
activationConditions
:
Ваша сцена настроена с помощьюactivationConditions
, которые наполняются предикатами. В данном случае вы используете предикат для проверки совпадения идентификаторов. Однако стоит отметить, что активация сцены может происходить на основе других факторов, помимо простого сравнения идентификаторов. -
Разные типы предикатов:
Обратите внимание, чтоcanActivateForTargetContentIdentifierPredicate
указывает, может ли сцена активироваться для данного идентификатора контента. ОднакоprefersToActivateForTargetContentIdentifierPredicate
указывает, что эта сцена заинтересована в активации для конкретного идентификатора. Если система считает, что у сцены сохраняется верное состояние, она может при этом игнорировать предикатcanActivateForTargetContentIdentifierPredicate
. -
Порядок проверки предикатов:
Система может обрабатывать предикаты в определенного рода порядке и при наличии нескольких факторов, сигнализирующих о возможной активации. Например, если у вас есть пользовательская активность, которая затем может “подтолкнуть” систему к активации сцены, это может произойти, даже еслиcanActivateForTargetContentIdentifierPredicate
не соответствует условиям. -
Проверка на наличие пользовательской активности:
Если вconnectionOptions
или состоянии восстановления сессии передается какая-либо пользовательская активность, она также может привести к активации сцены, независимо от предикатов. Если ваше приложение обрабатывает эту активность, то это может оказаться решающим фактором при активации. -
Код с использованием
NSPredicate(value: false)
:
Интересный момент в том, что, когда вы инициализируетеNSPredicate(value: false)
и присваиваете егоcanActivateForTargetContentIdentifierPredicate
, и сцена все равно активируется, это может указывать на то, что существуют другие механизмы или триггеры, которые активируют сцену. Возможно, это связано с внутренними механиками iOS, где не только предикаты предопределяют активацию, но и общая логика вашего приложения. -
Рекомендации по отладке:
- Убедитесь, что вы проверили все возможные источники активностей, которые могут повлиять на активацию сцены.
- Проверьте, нет ли других мест в коде, где состояние сцены, пользовательские действия или какие-то другие условия могут изменять логику активации.
- Используйте отладочные сообщения для отслеживания выполнения кода, чтобы понять, какие именно активности вызывают активацию сцены.
В заключение, несмотря на то, что заданная логика со стороны предикатов актуальна, активация сцен в системе может происходить из-за других факторов. Не забывайте тщательно отслеживать и проверять весь контекст, в котором происходит активация, чтобы выявить проблему.