1.) Являются ли очереди NSOperation разумным выбором? Если нет, то что еще?
NSOperationQueue звучит так, как будто это было бы разумно.
конечно, у вас есть выбор: pthreads, libdispatch (также известный как GCD), библиотеки потоков C++, построенные поверх pthreads, и т. д., и т. д., и т. д. если вы не создаете много/много, то все сводится к модели, которую вы предпочитаете .
2.) Как минимизировать сон? (Очевидно, я хочу, чтобы работа выполнялась как можно чаще/в разумных пределах, и я не уверен, что мои сны вообще что-то делают для обновления всего пользовательского интерфейса.)
не спите =) вы можете использовать таймер для ваших элементов пользовательского интерфейса или явный обратный вызов или уведомление для уведомления о зависимостях. если зависимости выполняют обновления пользовательского интерфейса, то вы, скорее всего, добавите сообщение в очередь сообщений основного потока.
3.) Есть ли лучший способ поддерживать пользовательский интерфейс в актуальном состоянии? Например, могу ли я использовать NSTimer или какой-либо другой метод для отправки сообщения пользовательскому интерфейсу с указанием обновить и/или проверить состояние кнопок?
это действительно зависит от того, что вы делаете. если вы просто хотите обновить индикатор выполнения, вы можете записать значение из вторичного потока и прочитать значение из основного потока. затем используйте таймер в основном цикле выполнения, чтобы периодически сообщать вашему объекту об обновлении его отображения (на основе текущего значения). для чего-то вроде неустановленного индикатора прогресса это может быть хорошо.
другой вариант более полезен для событий или этапов: он будет включать в себя публикацию обновлений (например, уведомлений или обратных вызовов делегату) из вторичного потока по мере выполнения (дополнительная информация в № 2).
Обновить
Я не был уверен, что это уместно в модели iOS, но похоже, что это так.
да, это нормально - есть много подходов, которые вы можете использовать. что «лучше» зависит от контекста.
Мое текущее понимание заключается в том, чтобы запускать пользовательский интерфейс в одном потоке (не в основном!),
вы действительно не запускаете пользовательский интерфейс явно; основной поток (обычно) управляется отправкой событий и сообщений в основной поток. основной поток использует цикл выполнения и обрабатывает поставленные в очередь сообщения/события на каждой итерации цикла выполнения. вы также можете запланировать эти сообщения в будущем (подробнее об этом чуть позже). сказав это, все ваши сообщения объектам UIKit и AppKit (если вы нацелены на osx) должны быть в основном потоке (в качестве обобщения, которое вы в конечном итоге узнаете, есть исключения из этого). если у вас есть конкретная реализация, которая полностью отделена от методов обмена сообщениями объектов UIKit, и эта программа является потокобезопасной, то вы можете фактически выполнять эти сообщения из любого потока, поскольку это не влияет на состояние реализации UIKit. простейший пример:
@interface MONView : UIView
@end
@implementation MONView
// ...
- (NSString *)iconImageName { return @"tortoise.png"; } // pure and threadsafe
@end
запустите мой рабочий поток, используйте таймер для генерации сигнала пользовательскому интерфейсу, чтобы посмотреть на значение прогресса и соответствующим образом обновить индикатор выполнения. Для целей этого конкретного приложения вашего предпоследнего абзаца вполне достаточно, и мне не нужно углубляться в последний абзац (по крайней мере, на данный момент). Спасибо.
для этого вы можете использовать подход, подобный этому:
@interface MONView : UIView
{
NSTimer * timer;
MONAsyncWorker * worker; // << this would be your NSOperation subclass, if you use NSOperation.
}
@end
@implementation MONView
// callback for the operation 'worker' when it completes or is cancelled.
- (void)workerWillExit
{
assert([NSThread isMainThread]); // call on main
// end recurring updates
[self.timer invalidate];
self.timer = nil;
// grab what we need from the worker
self.worker = nil;
// update ui
}
// timer callback
- (void)timerUpdateCallback
{
assert([NSThread isMainThread]); // call on main
assert(self.worker);
double progress = self.worker.progress;
[self updateProgressBar:progress];
}
// controller entry to initiate an operation
- (void)beginDownload:(NSURL *)url
{
assert([NSThread isMainThread]); // call on main
assert(nil == worker); // call only once in view's lifetime
// create worker
worker = [[MONAsyncWorker alloc] initWithURL:url];
[self.operationQueue addOperation:worker];
// configure timer
const NSTimeInterval displayUpdateFrequencyInSeconds = 0.200;
timer = [[NSTimer scheduledTimerWithTimeInterval:displayUpdateFrequencyInSeconds target:self selector:@selector(timerUpdateCallback) userInfo:nil repeats:YES] retain];
}
@end
обратите внимание, что это очень примитивная демонстрация. также более распространено помещать таймер, обработку обновления и операцию в контроллер представления, а не в представление.
person
justin
schedule
13.09.2011