根据Best way to remove from NSMutableArray while iterating?,我们不能在迭代时从NSMutableArray中删除对象,是的。
但是,如果我有如下代码,该怎么办
- (void)sendFeedback {
NSMutableArray *sentFeedback = [NSMutableArray array];
for (NSMutableDictionary *feedback in self.feedbackQueue){
NSURL *url = [NSURL URLWithString:@"someApiUrl"];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:[feedback objectForKey:@"data"] forKey:@"data"];
[request setCompletionBlock:^{
[sentFeedback addObject:feedback];
}];
[request startAsynchronous];
}
[self.feedbackQueue removeObjectsInArray:sentFeedback];
}
我正在使用NSRunLoop创建一个NSThread来每隔一段时间执行一次sendFeedback方法。我向api发送数据的方式是使用异步方法(该方法将为每个请求创建一个后台线程)发送反馈后,必须将其删除,然后NSRunner在下一次执行此方法以避免重复数据提交。
通过使用异步,循环(主线程)将继续运行,而无需等待服务器的响应。在某些情况下(也许是大多数情况),循环将在每个请求的服务器响应全部返回之前完成运行。如果是这样,则完成块的代码将在 removeObjectsInArray 之后执行,这将导致发送的数据保留在self.feedbackQueue中
我很确定有几种方法可以避免该问题。但是我唯一想到的是使用同步方法,以便在所有请求的响应返回之前(成功或失败),不执行 removeObjectsInArray 。但是,如果这样做,则意味着必须较长时间连接互联网。 sendFeedback的线程所需的时间将更长。即使它将由新创建的NSThread运行,这也不会导致应用程序不响应,反正仍然需要资源。
那么,除了我上面提到的以外,还有其他方法吗?任何建议都欢迎。
谢谢。
最佳答案
有几种方法可以解决此类问题。我建议使用一个调度组来同步您的反馈,并使用一个实例变量来防止新的反馈批仍在进行中。对于此示例,假设您为类创建了一个名为_feedbackUploadInProgress
的实例变量,则可以像这样重写-sendFeedback
方法:
- (void)sendFeedback
{
if( _feedbackUploadInProgress ) return;
_feedbackUploadInProgress = YES;
dispatch_group_t group = dispatch_group_create();
NSMutableArray *sentFeedback = [NSMutableArray array];
for (NSMutableDictionary *feedback in self.feedbackQueue) {
// enter the group for each item we're uploading
dispatch_group_enter(group);
NSURL *url = [NSURL URLWithString:@"someApiUrl"];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:[feedback objectForKey:@"data"] forKey:@"data"];
[request setCompletionBlock:^{
[sentFeedback addObject:feedback];
// signal the group each time we complete one of the feedback items
dispatch_group_leave(group);
}];
[request startAsynchronous];
}
// this next block will execute on the specified queue as soon as all the
// requests complete
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
[self.feedbackQueue removeObjectsInArray:sentFeedback];
_feedbackUploadInProgress = NO;
dispatch_release(group);
});
}
关于objective-c - 从迭代NSMutableArray中删除对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10022687/