Поставить в очередь селектор в цикле выполнения - это [NSObject executeSelector: withObject: afterDelay:] путь? - PullRequest
9 голосов
/ 14 ноября 2009

Я бы хотел, чтобы метод был выполнен после того, как текущий метод прошел и пользовательский интерфейс был обновлен. Для этого я использую [object performSelector:@selector(someSelector) withObject:someObject afterDelay:0.0] прямо сейчас. Согласно документации Apple , создается NSTimer, который затем запускает и добавляет селектор к текущему NSRunLoop. Но я не считаю это очень элегантным. Есть ли простой способ напрямую поставить селектор в очередь к текущему циклу выполнения, не заставляя Какао создавать таймер и т. Д .?

Будет ли performSelectorOnMainThread:withObject:waitUntilDone: (если я в главном потоке) или performSelector:onThread:withObject:waitUntilDone: с waitUntilDone:NO делать то, что я хочу, с меньшими издержками?

Приветствия и заранее спасибо

MrMage

Ответы [ 4 ]

6 голосов
/ 14 ноября 2009

Какао управляется событиями. Вы не «ставите в очередь селектор в текущем цикле выполнения». Проще говоря: событие, отправляемое приложению (пользовательский ввод, таймер, сетевая активность ...), приводит к выполнению цикла выполнения, что приводит к тому, что происходит при этом запуске цикла. Конечно, есть «детали», но это самое основное поведение.

Если вы хотите отложить выполнение какого-либо селектора до конца текущего цикла выполнения, вызовите его последним или попросите запустить его на (очень близком) грядущем запуске цикла. -PerformSelector: ... методы являются правильным способом сделать это. Они создают таймер, который приводит к событию, которое вызывает события.

Для получения дополнительной информации см. Руководство по обработке событий Какао .

4 голосов
/ 15 ноября 2009

Я предпочитаю метод NSRunLoop "executeSelector: target: аргумент: order: mode:". Гарантируется, что селектор не будет выполняться до следующей итерации цикла выполнения, и вам не придется возиться с указанием произвольных задержек и т. Д.

4 голосов
/ 14 ноября 2009

Я не вижу ничего неуместного в -performSelector: withObject: afterDelay: метод, который вы выделите. Этот метод просто ставит в очередь задачу, которая должна быть выполнена после завершения текущего цикла цикла выполнения. Из документации в разделе, на который вы ссылаетесь :

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

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

Для более явных многопоточных очередей вы можете посмотреть NSOperations и NSOperationQueues . NSOperationQueue с maxConcurrentOperationCount, равным 1, может выполнять операции по порядку, одну за другой.

2 голосов
/ 15 ноября 2009

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

performSelectorOnMainThread:withObject:waitUntilDone:NO.

Тот факт, что вы уже находитесь в главном потоке, не означает, что он не будет работать (на самом деле документы ссылаются на поведение, которое будет происходить при вызове из основного потока) ... и я думаю, что оно будет иметь такое же поведение, когда Параметр waitUntilDone имеет значение NO, где он ставит в очередь запрос на выполнение селектора и запускает его по окончании текущего цикла выполнения.

...