Concurrent NSOperation and how to set isFinished and isExecuting?

久未见 提交于 2019-12-13 04:42:37

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!