问题
I am trying to split up my programs flow using NSOperations. I am using the Parse framework to make a simple messaging app. I want to display some messages and then delete them. The display messages shouldn't be called unless the delete operations is finished so I want to try using an NSQueue and add a displayMessages operation to it and then a deleteMessages operation (named MyOperation below). I understand that concurrent operations means they will only execute one after another in a queue fashion. Below is my code for the delete method. Is there a way to manually tell the operation it is finished i.e. setting isFinished or isExecuting??
// MyOperation.h
@interface MyOperation : NSOperation {
@property (strong, nonatomic) NSMutableArray *toDelete;
}
@end
And the implementation:
// MyOperation.m
@implementation MyOperation
- (id)initWithArray:(NSMutableArray *)array
{
self = [super init];
if (self == nil)
return nil;
_toDelete=array;
}
- (void)main {
if ([self isCancelled]) {
NSLog(@"** operation cancelled **");
}
//how do I get main to finish execution ONLY after deleteAllInBackground has finished?
[PFObject deleteAllInBackground:self.toDelete];
if ([self isCancelled]) {
NSLog(@"** operation cancelled **");
}
NSLog(@"Operation finished");
}
@end
right now this code above won't solve my problem. It will queue up the ops but this one will finish even though the deleteAllInBackground is still running. Would really appreciate some help here! thanks
other possible solution:
-(void)receivedMessage
{
NSLog(@"push!");
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
[self displayMessages];
dispatch_async(dispatch_get_main_queue(), ^(void){
if([self.toDelete count]>0) {
[PFObject deleteAllInBackground:self.toDelete];
}
});
});
}
回答1:
I would suggest you to use dispatch_async
like below;
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
dispatch_async(dispatch_get_main_queue(), ^(void){
// Display messages
});
// Delete messages here
});
If you have to use NSOperationQueue
then I would suggest you to use KVO
to get notification for task completion; When you setup your queue, do this:
[self.deleteQueue addObserver:self forKeyPath:@"delete-operations" options:0 context:NULL];
Then do this in your observeValueForKeyPath
:
- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context {
if (object == self.deleteQueue && [keyPath isEqualToString:@"delete-operations"]) {
if ([self.queue.operations count] == 0) {
// Delete operation done
// Display messages here
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object
change:change context:context];
}
}
[EDIT]
-(void)receivedMessage {
@synchronized(self) {
NSLog(@"push!");
dispatch_async(dispatch_get_main_queue(), ^(void) {
[self displayMessages];
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
if([self.toDelete count]>0) {
// this deletion doesn't matter if background or on main thread as it's already in background queue
[PFObject deleteAllInBackground:self.toDelete];
}
});
});
}
}
回答2:
Use deleteAll
instead of deleteAllInBackground
if you want to block the current thread until the deletion is complete.
来源:https://stackoverflow.com/questions/28154011/concurrent-nsoperation-and-how-to-set-isfinished-and-isexecuting