Reputation: 15039
I have to do a IO operation which might take long to complete. The IO oeration is invoked from a button. Ofcourse the UI hangs untill the operation completes. So I suppose I need to do IO on some background thread, but when the operation completes I have to update window's labels to signal the operation complete. Which I suppose I should be doing on the main thread (like EDT in java and similar in C#) , correct ?
in C# there is class something like TaskAsync and similar in Java android. Which lets you complete the long task in another thread and the when the task is complete a handler is called on main thread , so that UI can be updated on main thread,
What exactly does cocoa has to do similar task, that is allow a long operation on seperate thread than main and then somehow facilitate to update the userinterface on main thread.
Upvotes: 0
Views: 1306
Reputation: 89509
Assuming you have a handle to the view controller where you want to update the UI, you could use the NSObject "performSelectorOnMainThread:withObject:waitUntilDone:
" method.
2) you could also utilize Grand Central Dispatch with code like this:
dispatch_async(dispatch_get_main_queue(), ^{
[viewController doSomethingWhenBigOperationIsDone];
});
3) Or you could even post an NSNotification from your background thread where the observer (in the main thread) could update the UI.
You might find some additional useful information in this related question.
Upvotes: 0
Reputation: 5683
Your long running operation should be moved to an NSOperation subclass
AhmedsOperation.h
@interface AhmedsOperation : NSOperation
@end
AhmedsOperation.m
@implementation AhmedsOperation
// You override - (void)main to do your work
- (void)main
{
for (int i = 0; i < 1000; i++) {
if ([self isCancelled]) {
// Something cancelled the operation
return;
}
sleep(5);
// Emit a notification on the main thread
// Without this, the notification will be sent on the secondary thread that we're
// running this operation on
[self performSelectorOnMainThread:@(sendNotificationOnMainThread:)
withObject:[NSNotification notificationWithName:@"MyNotification"
object:self
userInfo:nil]
waitUntilDone:NO];
}
}
- (void)sendNotificationOnMainThread:(NSNotification *)note
{
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc postNotification:note];
}
Then in your main code, when you want to do your operation you just create an AhmedsOperation object, and push it to an NSOperationQueue and listen to the notifications.
AhmedsOperation *op = [[AhmedsOperation alloc] init];
NSOperationQueue *defaultQueue = [MLNSample defaultOperationQueue];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:@selector(progressUpdateNotification:)
name:@"MyNotification"
object:op];
[defaultQueue addOperation:op];
Upvotes: 1