Страница на основе reloadRootControllersWithNames: в цикле запуска?

- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
    [WKInterfaceController reloadRootControllersWithNames:@[@"pageOne", @"pageTwo"] contexts:nil];
}

Следуя рекомендациям Apple

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

во время запуска приводит только к циклу. При каждой перезагрузке вызов awakeWithContext или активируется или инициализируется снова и снова.

Есть ли лучший способ перезагрузить приложение Page-Based при запуске с циклом?


person devone    schedule 10.03.2015    source источник
comment
awakewithcontext вызывается каждый раз, когда вы вызываете reloadRootControllersWithNames, поэтому это приводит к циклу. Просто настройте базовую навигацию по страницам по умолчанию в раскадровке.   -  person Javier Flores Font    schedule 10.03.2015
comment
Да, я неправильно прочитал документы Apple, предполагая, что во время запуска он должен был сделать всю работу за вас.   -  person devone    schedule 10.03.2015


Ответы (4)


Это распространенная проблема с приложениями WatchKit, поскольку у нас больше нет UIApplicationDelegate для такой настройки. Хорошим подходом было бы структурировать код следующим образом:

  • MainInterfaceController (основная ссылка в раскадровке указывает здесь)
  • PageOneInterfaceController — ваш первый интерфейс для отображения в наборе страниц
  • PageTwoInterfaceController - ваш второй интерфейс в наборе страниц

На самом деле MainInterfaceController никогда не будет отображаться. Вы всегда будете запускать другой набор контроллеров интерфейса в зависимости от кэшированного состояния сопутствующего приложения iOS в MainInterfaceController.awakeWithContent(). Таким образом, вы используете MainInterfaceController так же, как мы используем UIApplicationDelegate в iOS для настройки окна и корневого контроллера представления.

Я использовал этот подход в приложении, в котором было много разных наборов страниц на выбор, и это сработало очень хорошо.

person cnoon    schedule 10.03.2015
comment
Вау, блестяще, это умная тренировка, я собирался использовать кучу логических значений и не ждал этого. Большое спасибо! - person devone; 10.03.2015
comment
reloadRootControllersWithNames — это не вызывает деактивацию уже имеющихся контроллеров. Любые решения, если что-то нужно остановить (например, таймер) на контроллере, который был виден? - person Rohit Gupta; 05.04.2015
comment
@cnoon Я использовал это, чтобы представить правильный контроллер WKInterface из удаленного уведомления. В итоге я звоню reloadRootControllersWithNames дважды, один раз в awakeWithContext моего MainInterfaceController и один раз в - (void)handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)remoteNotification. Однако я сначала вижу три точки в элементе управления страницей, которые затем становятся двумя. Любой способ избежать этого? Я подхожу к этому правильно? - person Walter Martin Vargas-Pena; 13.04.2015

Вот почему awakeWithContext: существует. При первом запуске приложения начальный контроллер передается nil как context. Но если вы reloadRootControllersWithNames:contexts:, у вас есть возможность передать экземпляр пользовательского контекста и, таким образом, отличить режим запуска.

person Aleks N.    schedule 10.07.2015
comment
Это гораздо более простой и чистый подход, спасибо! - person Dmorneault; 11.04.2017
comment
Я тоже так реализую! - person sudoExclaimationExclaimation; 10.12.2018

вызов WKInterfaceController.reloadRootControllers вызывает второй вызов функции пробуждения. Это решение, которое я использую - оно простое, компактное и устраняет рекурсивный цикл. В этом примере есть два представления на основе страниц, называемые mainControls и nowPlaying, которые настроены с контекстами. Обратите внимание, что ключевым моментом здесь является настройка контроллера представления mainControls с контекстом пустой строки, затем этот контекст проверяется и возвращается, если он вызывается снова из-за инструкции WKInterfaceController.reloadRootControllers, которая настроила контекст на «». Обратите внимание, что при первом пробуждении контекст для основного контроллера представления будет нулевым. Также обратите внимание, что второй контекст — это деталь реализации, специфичная для моей реализации — это может быть любой объект, который вы хотите передать второму контроллеру представления.

override func awake(withContext context: Any?) {
    super.awake(withContext: context)
    if let _ = context as? String {
        print("already configured!")
        return
    }
    print("configuring...")
    WKInterfaceController.reloadRootControllers(withNames: ["mainControls", "nowPlaying"], contexts: ["", interaction])
}
person Richie Hyatt    schedule 25.11.2018

Действительно легко решить и не требует нескольких контроллеров страниц - просто используйте один раз

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

static NSString* hasLaunchedIfNotNullString = NULL;

- (void)awakeWithContext:(id)context
{
    if(hasLaunchedIfNotNullString == NULL)
    {
        //START Code which gets executed once
        hasLaunchedIfNotNullString = @"";

        ...
        [WKInterfaceController reloadRootControllersWithNames:YOUR_ARRAY contexts:CONTEXTS];
        // END code which gets executed once
    }
}
person Clint Johnson    schedule 26.06.2015
comment
Использование строкового поля в качестве флага, как правило, является плохой идеей. - person Aleks N.; 10.07.2015