1.) Является ли Очередь NSOperation разумным выбором?Если нет, то что еще?
NSOperationQueue звучит так, как будто это было бы разумно.
конечно, у вас есть выбор: pthreads, libdispatch (он же GCD), библиотеки потоков c ++, построенные сверхуpthreads и т. д. и т. п., если вы не порождаете много / много, то это просто сводится к модели, которую вы предпочитаете.
2.) Как минимизировать сон?(Очевидно, я хочу, чтобы работа выполняла как можно больше циклов, насколько это возможно / разумно, и я не уверен, что мои сны вообще что-то делают для обновления всего пользовательского интерфейса.)
неsleep =) вы можете использовать таймер для ваших элементов пользовательского интерфейса или явный обратный вызов или уведомление для уведомления о зависимостях.если зависимости обновляют пользовательский интерфейс, вы, скорее всего, добавите сообщение в очередь сообщений основного потока.
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
Обратите внимание, что это очень примитивная демонстрация.также чаще помещают таймер, обработку обновлений и операции в контроллере представления, а не в представлении.