为了稍微扩展@danh的答案,我会说你不应该有一个指向该对象的指针,直到它全部完成。例如:
[MyObject makeObjectWithID:123 completion:^(MyObject *object, NSError *error) {
if (object == nil) {
NSLog(@"error creating object: %@", error);
} else {
NSLog(@"created object: %@", object);
}
}];
然后创建方法将是这样的:
+ (void)makeObjectWithID:(NSInteger)objectID completion:(void(^)(MyObject*,NSError*))handler {
handler = Block_copy(handler);
dispatch_async(dispatch_get_global_queue(0,0), ^{
MyObject *object = [[MyObject alloc] initWithID:objectID];
NSError *error = nil;
BOOL succeeded = [object doTheExpensiveAndBlockingSetupThingWithError:&error];
if (succeeded == NO) {
[object release], object = nil;
}
dispatch_async(dispatch_get_main_queue(), ^{
handler([object autorelease], error);
});
});
Block_release(handler);
}
原则上,我发现你制作的 API 越安全,你搞砸的可能性就越小。这种方式是安全的,因为您永远不会有指向部分构造的MyObject
. 你不可能得到一个并且没有完全准备好使用。当然,没有取消机制,但您仍然可以扩展它以允许这样做。