iOS:使用在后台运行的方法进行For循环?

时间:2016-03-12 08:55:42

标签: ios objective-c for-loop objective-c-blocks

我有一个id数组,我在其中运行for循环,并调用在后台运行的方法(进行网络调用以获取数据)。我如何知道for循环何时完成以及所有调用都已完成?

此时for循环在所有预期的调用完成之前完成。我应该使用while循环吗?

更新(终于搞定了!)

我在这里发布了我的代码,希望它能帮助别人。 :)

详细信息:根据Andrey的建议,我做的第一件事是继承NSOperation并执行以下操作:

@interface AsyncOperation ()

@property (atomic, assign) BOOL _executing;
@property (atomic, assign) BOOL _finished;

@end

@implementation AsyncOperation

- (void)start {

    if ([self isCancelled]) {

        //Move the operation to the finished state if it is canceled.
        [self willChangeValueForKey:@"isFinished"];
        self._finished = YES;
        [self didChangeValueForKey:@"isFinished"];
        return;
    }

    //If the operation is not canceled, begin executing the task.
    [self willChangeValueForKey:@"isExecuting"];
    [NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil];
    self._executing = YES;
    [self didChangeValueForKey:@"isExecuting"];

}

- (void)main {
    if ([self isCancelled]) {
        return;
    }
}

- (BOOL)isAsynchronous {
    return YES;
}

- (BOOL)isExecuting {
    return self._executing;
}

- (BOOL)isFinished {
    return self._finished;
}

//Make sure to expose this method in the header file
- (void)completeOperation {

    [self willChangeValueForKey:@"isFinished"];
    [self willChangeValueForKey:@"isExecuting"];

    self._executing = NO;
    self._finished = YES;

    [self didChangeValueForKey:@"isExecuting"];
    [self didChangeValueForKey:@"isFinished"];
}

最后,在我的方法中,我做了:

    //Setup NSOperation Queue
    self.queue = [[NSOperationQueue alloc] init];
    self.queue.name = @"myQueue";

    //Set Queue Observer (Using Third Party Library KVOController)
    [self.KVOController observe:self.queue keyPath:@"operationCount" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew block:^(id observer, NSOperationQueue *queue, NSDictionary *change) {

        //Check if all operations concluded
        if (queue.operationCount == 0) {

            //Remove Observer
            [self.KVOController unobserve:self.queue];

            //DO SOMETHING NOW THAT EVERYTHING IS DONE
        }
    }];

    //Loop through my chats and fetch each one
    for (NSString *chatId in chatIds) {

        //Observe Operation
        AsyncOperation *operation = [[AsyncOperation alloc] init];
        [self.KVOController observe:operation keyPath:@"isExecuting" options:NSKeyValueObservingOptionNew block:^(id observer, EMKAsyncOperation *myOperation, NSDictionary *change) {

            //Check if operation is executing
            if ([myOperation isExecuting]) {

                //Fetch Chat (My async method)
                [self fetchChatWithId:chatId inBackgroundWithBlock:^(Chat *chat, BOOL succeeded, NSError *error) {

                    //Check for error
                    if (!error) {

                        //DO WHATEVER I DO AFTER FETCHING COMPLETED

                        //Complete operation manually 
                        [myOperation completeOperation];

                        //Remove Observer
                        [self.KVOController unobserve:myOperation];

                    } else {

                       //Error Cancel Everything
                       finalError = error;

                       NSLog(@"Error fetching all chats: %@", [error localizedDescription]);

                       //Cancel Operations
                       [self.queue cancelAllOperations];

                        //Complete operation
                        [myOperation completeOperation];

                        //Remove Observer
                        [self.KVOController unobserve:myOperation];
                    } 
                }];
            }
        }];

        //Add Operation
        [self.queue addOperation:operation];
    }

希望这有助于人们!

2 个答案:

答案 0 :(得分:5)

似乎问题不在于找出循环何时完成,这很明显,而是在所有网络调用完成时。 所以这就是我要做的。我将每个网络调用包装到NSOperation类的实例中,并将每个操作添加到NSOperationQueue中。此类具有operationsCount属性,这是可观察的键值。因此,使用KVO可以观察到此属性的变化。一旦operationsCount等于0,您就完成了。所有请求都已完成

答案 1 :(得分:2)

创建一个整数变量,并在调用完成块时递增它。通过这种方式,您可以了解自己有多少回复。如果该count == array.count,则已收到所有响应。