Изменение свойства 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 в мою модель, чтобы она могла сохраняться и обрабатываться лучше, независимо от того, какое представление отображается.
Я также изменил свой блочный код, чтобы использовать указатель слабого себя внутри блока, чтобы, надеюсь, не дать этому блоку сохранить какой-либо объект исключительно из-за того, что блок остался позади.
Приветствую всех!