2014-01-25 2 views
0

Для начала, я понимаю, что может быть причиной этой проблемы путем решения предыдущей задачи неправильно ...Стоп ребенок темы от `` performSelector` на viewDidDisappear`

В ViewController основном потоке Я начинаю фоновый поток чтобы получить обновленные данные с сервера, используя:

[self performSelectorInBackground:@selector(sampleTask:) withObject:@"CMD" ]; 

Этот процесс может занять 15-30 секунд, так в основном потоке отобразить локальный кэш данных из базы данных SQLite (заполняется из предыдущего запроса на сервер в последний раз, когда вид был открыт) и перезагрузите таблицу после завершения синхронизации с сервером.

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

  • Есть ли способ остановить созданные потоки на спусковом крючке, например viewDidDisappear?
  • Или я должен писать блокировку для общего ресурса (например, NSUserDefaults), чтобы предотвратить запуск нового фонового потока?

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

+2

Эта строка кода не запускается фоновый поток. Он запускается в том же потоке, из которого он был вызван, только до истечения задержки. – rmaddy

+0

Извините, неправильный пример, performSelectorInBackground был тем, что я имел в виду. Тем не менее, все же наблюдается аналогичное поведение с performSelector. Если performSelector ведет себя таким образом, как я вижу, что «sampleTask» все еще работает после запуска viewDidDisappear. Я использую модели segues между видами. Когда уничтожен ViewController, который выполняет функциюSelector? Это часть, которую мне не хватает? – messinga

+0

Отредактировано OP, чтобы использовать фоновый поток, а не текущий поток. – messinga

ответ

1

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

+0

Это грязное, но единственное решение, которое я вижу на данный момент. – messinga

1

performSelector:withObject:afterDelay: не создает отдельную нить.

Процитирую часть документации по этому методу:

Запускает метод приемника на текущем потоке с использованием режима по умолчанию после задержки

Он использует таймер для запуска вашего селектора после задержки. Таким образом, он подвергается тем же ограничениям точности, что и NSTimer. (Метод performSelectorInBackground:withObject:делает отправьте свой селектор на фоне нити.)

Но вернемся к вашему вопросу.

Вы можете использовать метод

cancelPreviousPerformRequestsWithTarget:selector:object: 

Чтобы отменить отложенный вызов performSelector:withObject:afterDelay:

+0

Это точно не отвечает на мой вопрос ... cancelPreviousPerformRequestsWithTarget останавливает вызов, только если он все еще находится в временной шкале послеDelay. Однако полезно знать, что это может помешать выполнению селектора, если он еще не запущен. Но проблема по-прежнему будет заключаться в том, что селектор «sampleTask» все еще может работать при закрытии и повторном открытии (если пользователь достаточно быстро). – messinga

+0

Ну, нет. Поскольку performSelector: withObject: afterDelay: не запускает задачу в другом потоке, метод будет работать в основном потоке. Таким образом, пользователь не сможет ничего сделать, пока метод не завершится. –

Смежные вопросы