iOS:在后台使用 运行 方法的 For 循环?
iOS: For-loop with methods that run in the background?
我有一个 id 数组,其中我 运行 一个 for 循环,并在后台调用一个 运行s 的方法(进行网络调用以获取数据)。我如何知道 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];
}
希望这对人们有所帮助!
问题似乎不在于找出循环何时结束,这是显而易见的,而在于所有网络调用何时结束。
所以这就是我要做的。我会将每个网络调用包装到 NSOperation
class 的实例中,并将每个操作添加到 NSOperationQueue
中。此 class 具有 operationsCount
属性,这是可观察的键值。所以使用 KVO 你可以观察到这个 属性 的变化。一旦 operationsCount
等于 0 - 你就完成了。所有请求已完成
创建一个整数变量并在调用完成块时递增它。这样,您就可以了解收到了多少回复。如果该计数 == array.count,则已收到所有响应。
我有一个 id 数组,其中我 运行 一个 for 循环,并在后台调用一个 运行s 的方法(进行网络调用以获取数据)。我如何知道 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];
}
希望这对人们有所帮助!
问题似乎不在于找出循环何时结束,这是显而易见的,而在于所有网络调用何时结束。
所以这就是我要做的。我会将每个网络调用包装到 NSOperation
class 的实例中,并将每个操作添加到 NSOperationQueue
中。此 class 具有 operationsCount
属性,这是可观察的键值。所以使用 KVO 你可以观察到这个 属性 的变化。一旦 operationsCount
等于 0 - 你就完成了。所有请求已完成
创建一个整数变量并在调用完成块时递增它。这样,您就可以了解收到了多少回复。如果该计数 == array.count,则已收到所有响应。