1.) Are NSOperation Queues the smart choice? If not, what else?
NSOperationQueue sounds like it would be sensible.
of course you have a choice: pthreads, libdispatch (aka GCD), C ++ thread libraries created on top of pthreads, etc. etc., etc., if you do not create many / many, then it just comes down to the model you like.
2.) How to reduce sleep mode? (Obviously, I want as many cycles as possible), and I'm not sure that my sleep does anything at all for the entire user interface to update.)
do not sleep =) you can use a timer for your ui elements or an explicit callback or notification to notify dependencies. if ui dependency changes are updated, then you will most likely add a message to the message queue of the main thread.
3.) Is there a better way to keep the user interface up to date? For example, is it possible to use NSTimer or some other method to send a message to the user interface telling it to update and / or check the state of the buttons?
which really depends on what you do. if you just want to update the progress bar, then you can write the value from the secondary stream and read the value from the main stream. then use the timer in the main run loop to periodically report your object to refresh its display (based on the current value). for something like an indicator of unsteady progress, this might be good.
another alternative is more useful for events or stages: it will include the publication of updates (for example, notifications or callbacks for a delegate) from the secondary stream as it moves forward (for more details see No. 2).
Update
I was not sure if this was appropriate in the iOS model, but it looks like it is.
yes, thatβs fine - there are many ratings you can take. which is "best" depends on the context.
My real understanding is to run the interface in one thread (and not in the main one!),
you really do not start the user interface explicitly; the main thread (usually) is controlled by clicking events and messages on the main thread. the main thread uses a run loop and processes message / event queues at each iteration of the run loop. You can also plan these posts in the future (more on that a bit). saying that all your posts in UIKit and AppKit (if you are targeting osx) should be in the main thread (as a generalization, which you will eventually learn there are exceptions to this). if you have a specific implementation that is completely separate from the UIKit messaging methods and this program is thread safe, then you can actually execute these messages from any thread, because this does not affect the state of the UIKit implementation. The simplest example:
@interface MONView : UIView @end @implementation MONView // ... - (NSString *)iconImageName { return @"tortoise.png"; } // pure and threadsafe @end
start my workflow, use a timer to generate a signal for the user interface to look at the progress value and update the progress bar accordingly. For the purposes of this particular application, your second-last paragraph is enough, and I donβt need to go the length of the last paragraph (at least for now). Thanks.
for this you can use an approach similar to this:
@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 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
Please note that this is a very primitive demonstration. it is also more common to enable a timer, handle updates, and work in the view controller, rather than in a view.