ImDevinC
ImDevinC

Reputation: 528

NSOperationQueue and passing data

In my app, I have my main file that creates a new instance of a class and then uses NSOperationQueue to run the class functions in the background, like so:

NSOperationQueue backgroundQueue = [NSOperationQueue new];
MyClass mc = [MyClass alloc];
NSInvocationOperation* operation = [[NSInvocationOperation alloc] initWithTarget:mc selector:@selector(runEvents) object:nil];
[backgroundQueue addOperation:operation];

MyClass then does stuff in RunEvents, but I'm having difficulty passing data to the UI. I'm just trying to update a label on my storyboard, which I can do in my main class that calls MyClass, but how do I update it from MyClass?

Upvotes: 2

Views: 899

Answers (1)

Rob
Rob

Reputation: 437907

The typical answer is to create your class as a NSOperation subclass and give it a custom completion block. If your goal is update the UI or some model object in the completion block, make sure to dispatch that block back to the main queue:

//  CustomOperation.h

#import <Foundation/Foundation.h>

typedef void(^CustomOperationCompletion)(NSString *string);

@interface CustomOperation : NSOperation

@property (nonatomic, copy) CustomOperationCompletion customOperationCompletion;

- (id)initWithCustomCompletion:(CustomOperationCompletion)completion;

@end

and

//  CustomOperation.m

#import "CustomOperation.h"

@implementation CustomOperation

- (id)initWithCustomCompletion:(CustomOperationCompletion)completion {
    self = [super init];
    if (self) {
        self.customOperationCompletion = completion;
    }
    return self;
}

- (void)main {
    NSLog(@"%s starting", __FUNCTION__);

    sleep(5);

    NSString *string = [[NSDate date] description];

    if (self.customOperationCompletion) {
        [[NSOperationQueue mainQueue] addOperationWithBlock: ^{
            self.customOperationCompletion(string);
        }];
    }

    NSLog(@"%s ending", __FUNCTION__);
}
@end

Then you can invoke it with something like:

NSOperationQueue *queue = [[NSOperationQueue alloc] init];

CustomOperation *operation = [[CustomOperation alloc] initWithCustomCompletion:^(NSString *string) { 
    // update the UI with the results of the operation; here I'm just going to log it

    NSLog(@"all done, string=%@", string);
}];

[queue addOperation:operation];

Clearly, change your CustomOperationCompletion parameters to include whatever you want to return (I'm just passing a string back).

Upvotes: 2

Related Questions