Bea*_*red 4 asynchronous objective-c objective-c-blocks
我有一个简单的类,它公开了一种方法,该方法进行多个服务器调用以获取对象ID列表的对象数据。该方法枚举对象ID列表并进行单个服务器调用,如下所示...
@implementation MyClass
- (void)fetchObjectsFromServerWithObjectIDs:(NSArray*)objectIDs {
typeof(self) __weak blockSelf = self;
for(NSString *objectID in objectIDs) {
[self fetchObjectDataForObjectID:objectID withSuccessBlock:^{
if(objectID == [objectIDs lastObject]) { //<---will this work?
[blockSelf.delegate finishedFetching];
}
}];
}
}
- (void)fetchObjectDataForObjectID:(NSString*)objectID
withSuccessBlock:(void (^)())successBlock {
void (^successWrapperBlock)(void) = ^{
//Some processing of returned data is done here
if(successBlock) {
successBlock();
}
};
[HTTPClient fetchObjectDataWithObjectID:objectID
withSuccessBlock:successWrapperBlock
failureBlock:nil];
}
@end
Run Code Online (Sandbox Code Playgroud)
...我正在尝试找出检查最后一个程序successBlock是否正在执行的最佳方法,以便我可以告诉委托人它已完成数据的获取。我在代码“ <---这项工作会吗?”中有评论。标记正在执行检查的语句,但对我来说并不安全,因为该块是异步的,并且if(objectID == [objectIDs lastObject])在执行第一个successBock时可能为true。
如何确定何时执行最后一个successBlock?在此先感谢您的智慧!
这里的指针比较(objectID == [objectIDs lastObject])比较好,因为如果不修改数组,您将获得相同的对象。如果您担心objectIDs可能会被修改(例如,它实际上可能是一个可变数组,并在另一个线程上或通过诸如通知之类的副作用被修改),最好的保护就是在开始时复制该数组:
- (void)fetchObjectsFromServerWithObjectIDs:(NSArray*)objectIDs {
typeof(self) __weak blockSelf = self;
NSArray *copiedIDs = [objectIDs copy];
for(NSString *objectID in copiedIDs) {
[self fetchObjectDataForObjectID:objectID withSuccessBlock:^{
if(objectID == [copiedIDs lastObject]) {
[blockSelf.delegate finishedFetching];
}
}];
}
}
Run Code Online (Sandbox Code Playgroud)
现在有两种方法可以调用该委托:
这样你就可以:
因此,您可以这样做(@ChrisH的版本加上copy):
- (void)fetchObjectsFromServerWithObjectIDs:(NSArray*)objectIDs {
typeof(self) __weak blockSelf = self;
NSArray *copiedIDs = [objectIDs copy];
__block NSUInteger count = [copiedIDs count];
for(NSString *objectID in copiedIDs) {
[self fetchObjectDataForObjectID:objectID withSuccessBlock:^{
if(--count == 0) {
[blockSelf.delegate finishedFetching];
}
}];
}
}
Run Code Online (Sandbox Code Playgroud)
要么:
- (void)fetchObjectsFromServerWithObjectIDs:(NSArray*)objectIDs {
typeof(self) __weak blockSelf = self;
NSArray *copiedIDs = [objectIDs copy];
id lastObject = [copiedID lastObject];
for(NSString *objectID in copiedIDs) {
[self fetchObjectDataForObjectID:objectID withSuccessBlock:^{
if(objectID == lastObject) {
[blockSelf.delegate finishedFetching];
}
}];
}
}
Run Code Online (Sandbox Code Playgroud)