Из документации для -runMode:beforeDate:
:
Запускает цикл один раз […]
(Акцентдобавлено)
То есть этот метод не "зацикливает" цикл выполнения.Он просто блокирует один раз, ожидая срабатывания одного входного источника.Когда такой источник ввода срабатывает, метод возвращает.
Возвращаемое значение
ДА, если цикл выполнения выполнялся и обрабатывал источник ввода или было достигнуто указанное значение времени ожидания […]
Снова метод возвращается, когда «цикл выполнения был запущен и обработан входной источник или если было достигнуто указанное значение тайм-аута» (выделение добавлено).
[Этот метод] возвращается после обработки первого входного источника или достижения limitDate.
-performSelector:onThread:...
реализован как источник цикла выполнения, но это деталь реализации.В общем, если вы не запускаете цикл выполнения в пользовательском режиме, вы не можете полагаться только на то, что источники входного сигнала вашего приложения запланированы в цикле выполнения.Фреймворки могут планировать свои собственные источники на нем.Таким образом, вы должны быть готовы к тому, что этот метод вернется.
Итак, вы должны либо циклически переключаться между вызовами на -runMode:beforeDate:
, пока не произойдет какое-то условие, соответствующее вашим целям, либо вам придется использовать пользовательский режим идля таймера и при запуске цикла выполнения.В последнем случае, однако, вам нужно запланировать собственный источник ввода для этого режима, потому что просто таймера недостаточно, чтобы цикл выполнения продолжал работать.