我想在對象初始化期間卸載一些繁重的工作。我添加了一個status屬性,當我完全初始化了我的對象的所有其他實例變量時,我設置了該屬性。我必須通過下面的例子中簡化了我的整個做法:問題在多線程環境中獲取正確的屬性值
這是我的課(美孚),有我的初始化:
// - 頭文件
#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準備好,爲什麼我不能讓我的主線程中正確的價值?
在主線程中記錄'foo.status'的完成塊中,是否設置了'foo'?看看'foo'是否爲'nil'。 – rmaddy 2014-10-01 05:20:13
如果您要從多個線程訪問屬性,您應該將其聲明爲「atomic」而非「nonatomic」。此外,派遣組可能是更好的方法https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html#//apple_ref/doc/uid/TP40008091-CH102- SW25 – Paulw11 2014-10-01 05:31:21
只是爲了歡笑,聲明後備存儲變量'_status'並使其成爲'volatile BOOL',看看是否有幫助。 – borrrden 2014-10-01 06:26:00