I have a simple class with two ivars, a NSMutableArray and a BOOL. Objects of this class are able to shuffle elements in the array when they are sent the startShuffling message. They do so until they receive the stopShuffling message.
To make it work, the startShuffling method set the boolean to YES, and then dispatch the block of code that shuffles (while(self.isShuffling) { //... } on a concurrent queue. The stopShuffling set the boolean to NO, so that the shuffling process will terminate on the next loop turn.
Here is the interface :
@interface MyClass : NSObject <NSCoding> {
@private
NSMutableArray *elements_;
__block BOOL isShuffling_;
}
@property(readonly) BOOL isShuffling;
-(void)startShuffling;
-(void)stopShuffling;
@end
And the implementation :
@implementation MyClass
@synthesize isShuffling = isShuffling_;
-(void)startShuffling {
if(self.isShuffling) {
return;
}
isShuffling_ = YES;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
while(isShuffling_) {
// code that shuffles, one element by turn
NSUInteger elementIndex = arc4random() % [elements_ count];
id c = [[elements_ objectAtIndex:elementIndex] retain];
[elements_ removeObjectAtIndex:elementIndex];
[elements_ insertObject:c atIndex:[elements_ count]];
[c release];
}
});
}
-(void)stopShuffling {
isShuffling_ = NO;
}
@end
My class conforms to NSCoding protocol and I don’t want to abort encoding even if the object is shuffling. Instead I want my object to stop shuffling and then encode itself. So I have written this encoding method :
-(void)encodeWithCoder:(NSCoder *)aCoder {
if(self.isShuffling) {
[self stopShuffling];
}
[aCoder encodeObject:elements_ forKey:kIVPCodingKeyMyClassElements];
}
Finally, here my question.
I think it is possible for the encodeObject:forKey: method to get called while the shuffling loop terminates its last turn (maybe I’m wrong ?).
Is there any way I can make encodeObject:forKey: method get called after wait for the shuffling loop last turn to terminate ?
Yes, the the shuffle code may still be running when the
encodeObject:forKey:method is called.In general, you don’t want to dispatch some random block off onto a queue that executes for a really long time, potentially forever. You want to break up the work into blocks of work. And there-in lies your answer.
Something like:
Or something.