我试图在对象初始化期间卸载一些繁重的工作。我已经添加了一个status属性,当我完全初始化了我的对象的所有其他实例变量时,我设置了该属性。我通过以下示例简化了我的整个方法:
这是我的类(Foo),它有我的初始值设定项:
// - 头文件
#import <Foundation/Foundation.h>
typedef void (^loadingCompletionBlock)(BOOL success);
typedef NS_ENUM(NSInteger, FooStatus) {
FooCreated,
FooReady,
FooFailed,
};
@interface Foo : NSObject
+ (id) withCompletionBlock:(loadingCompletionBlock) block;
@property (assign, nonatomic) FooStatus status;
@end
// - 实施文件
@implementation Foo
- (FooStatus) status {
__block FooStatus readStatus;
dispatch_sync([Foo concurrentLoadingQueue], ^{
readStatus = _status;
});
return readStatus;
}
+ (dispatch_queue_t)concurrentLoadingQueue
{
static dispatch_queue_t sharedQueue;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedQueue = dispatch_queue_create("test.loadingQueue", DISPATCH_QUEUE_CONCURRENT);
});
return sharedQueue;
}
+ (id)withCompletionBlock:(loadingCompletionBlock) completed {
Foo* foo = [[Foo alloc] init];
foo.status = FooCreated;
dispatch_async([Foo concurrentLoadingQueue], ^{
for (int i=0; i<10000; i++)
{
NSLog(@"Running long tasks: %d", i);
}
foo.status = FooReady;
completed(YES);
NSLog(@"Foo status: %d (Background Thread)", foo.status);
});
return foo;
};
@end
我在主线程上调用以下代码:
Foo* foo = [Foo withCompletionBlock:^(BOOL success) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"Foo status: %d (Main Thread)", foo.status);
});
}];
NSLog(@"Foo status: %d (Main Thread)", foo.status);
NSLog会给我这些输出:
2014-10-01 07:09:49.606 TestConcurrentQueue[15610:60b] Foo status: 0 (Main Thread)
2014-10-01 07:09:52.818 TestConcurrentQueue[15610:1303] Running long tasks: 1
2014-10-01 07:09:52.818 TestConcurrentQueue[15610:1303] ......
2014-10-01 07:09:52.818 TestConcurrentQueue[15610:1303] Running long tasks: 9999
2014-10-01 07:09:52.818 TestConcurrentQueue[15610:60b] Foo status: 0 (Main Thread)
2014-10-01 07:09:52.818 TestConcurrentQueue[15610:1303] Foo status: 1 (Background Thread)
0正在创建状态,1为什么我无法在主线程中获得正确的值?
答案 0 :(得分:1)
我认为foo
在完成块中是nil
,因为正在创建foo
并将其作为原始方法调用的结果进行分配。
一个简单的解决方案是将创建的对象作为参数传递给完成块,以及BOOL
。
更好的方法可能是使withCompletionBlock:
实例方法而不是类方法。然后你的调用代码将是:
Foo* foo = [[Foo alloc] init];
[foo populateWithCompletionBlock:^(BOOL success) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"Foo status: %d (Main Thread)", foo.status);
});
}];
NSLog(@"Foo status: %d (Main Thread)", foo.status);
这样,完成块内的foo
引用了一个实际存在的对象。
init
的{{1}}方法会设置初始状态,而且全部都是。