Изменение свойства TableViewController, когда приложение находится в фоновом режиме

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

Моя проблема в том, что у меня есть контроллер табличного представления со свойством индекса NSInteger

   @property NSInteger index;

что я использую для постепенного управления медленной итерацией через NSArray, вызывая метод doWork.

Первоначальная настройка моего TVC и это свойство выполняется, когда представление готово для перехода из другого представления. Дополнительная работа над этим свойством и другими свойствами выполняется всякий раз, когда мое приложение получает локальные уведомления или после наблюдения UIApplicationWillEnterForegroundNotifications.

При каждом доступе к этому свойству я добавил отладочную логи, и я просто запутался в том, что вижу

  • PrepareForSegue
    • @ 19: 38: 29: 058 - вызывает метод doWork, который увеличивает мое свойство с -1 до 0 и устанавливает локальное уведомление. Логи показывают себя =0x10bb661f0
  • Я нажимаю кнопку "Домой", чтобы поместить приложение в фоновый режим на ~10 секунд.
  • Локальное уведомление срабатывает, и я нажимаю на баннер, чтобы вернуть мое приложение в фокус
  • Функция awakeFromNib моего TVC настраивает наблюдателя уведомлений следующим образом

    NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
    [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillEnterForegroundNotification 
                                                      object:nil
                                                       queue:mainQueue
                                                  usingBlock:^(NSNotification *note) {
                                                   [self doWork];
                                            }];
    
  • Это уведомление срабатывает дважды! (по какой-то причине?) каждый раз, вызывая мой метод doWork

    • @ 19:38:45:832 - doWork немедленно показывает, что мое свойство теперь возвращается к -1, а не к 0, для которого оно было задано до того, как оно было задокументировано, оно снова увеличивается до 0. Кроме того, оно показывает себя как отличающееся в self=0x10974bbd0, a ценность это остается в настоящее время, в то время как приложение заранее.
    • @ 19: 38: 45: 836 - doWork снова вызывается из этого 2-го вызова уведомлений, мое свойство теперь правильно по-прежнему 0 после последнего вызова, оно снова увеличивается до 1.
  • после этого мой делегат приложения также получает вызываемый метод didReceiveLocalNotification, который в конечном итоге также вызывает тот же метод doWork через другой блок в настройке наблюдателя Центра уведомлений, такой же, как описанный выше.
    • @ 19: 38: 45: 857 - вызывается doWork и снова свойство переходит из установленного значения 1 обратно в 0... и снова увеличивается до 1.

Я просто не могу понять, что происходит. Большинство свойств в моем TVC по-прежнему в порядке, так как остальная часть моей логики показывает, что содержимое TVC продолжает работать нормально. Почему мой NSInteger так изуродован?

Я подумал, что, возможно, могут быть некоторые проблемы с многопоточностью и локальной обработкой уведомлений, происходящей, возможно, одновременно, я надеялся, что добавление mainQueue поможет с этим, я ранее получил этот набор равным нулю. К сожалению, это не имело никакого значения.

Я удивляюсь, почему меняется самость после того, как ты находишься на заднем плане в течение короткого периода времени. Наивно я предполагал, что, поскольку все, похоже, работает над возвращением на передний план (представление все еще отображается, со всеми его данными, казалось бы, целыми, кроме этого свойства NSInteger), что self ptr и объект будут одинаковыми. Не так уж сложно представить, что, возможно, ОС каким-то образом была перемещена, но все же это не должно было вызвать изменение свойства.

Я использую какао-дровосека для регистрации, и я отключил протоколирование ASYNC следующим образом

    #define LOG_ASYNC_ENABLED NO 

Что должно, по крайней мере, означать, что вызовы журнала блокируются, пока они не войдут в систему. Я мог бы оценить, что если бы у меня были некоторые проблемы с многопоточностью, возможно, порядок регистрации был бы немного сомнительным. Но для первоначального искажения свойства, описанного выше, после того, как приложение входит в фоновый режим, есть ~10 секунд с того момента, как я записываю 0 в свойство, а затем считываю -1 обратно из него. Это явно не проблема синхронизации потоков в этот момент.

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

Есть ли проблема с моим использованием self в этом блоке, я видел, что иногда вы можете использовать слабые указатели self для этих блоков, но я видел примеры, где self также используется напрямую.

Любая помощь в понимании и, надеюсь, исправить это будет очень цениться. Я немного застрял и не вижу, что я сделал неправильно!

ура

1 ответ

Таким образом, ответ на мою проблему, как выяснили Woofbeans и Phillip Mills, заключается в том, что мой awakeFromNib вызывался каждый раз, когда я входил в этот TVC, а также мне не удавалось удалить Observer из этих уведомлений, из-за чего устаревшие невысказанные TVC оставались на неопределенное время. Я не понял эту ключевую часть моего воспроизведения проблемы.

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

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

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

Приветствую всех!

Другие вопросы по тегам