这是我的代码:
return
控制台打印1 和 2。
我想要的只是第一次打印1。我想也许hero-details
没有从方法返回,而是从块中返回。
有什么方法可以从这个GCD块中的当前方法返回?
答案 0 :(得分:3)
使用块来解决问题。
- (void)testGCD {
__block void(^codeBlock)(void) = ^{ NSLog(@"2"); };
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
codeBlock = ^{ NSLog(@"1"); };
});
codeBlock();
}
答案 1 :(得分:2)
- (void)testGCD {
static dispatch_once_t onceToken;
__block NSString *text = @"2";
dispatch_once(&onceToken, ^{
text = @"1";
});
NSLog(@"%@", text);
}
答案 2 :(得分:2)
如果您看到dispatch_once
的定义,那么您会发现他们正在使用DISPATCH_EXPECT
来比较onceToken
。您也可以使用if (onceToken != -1)
但DISPATCH_EXPECT
通过告诉编译器onceToken == -1
的概率要高得多来优化代码。这称为分支预测
- (void)testGCD {
static dispatch_once_t onceToken;
if (DISPATCH_EXPECT(onceToken, ~0l) != ~0l) {
dispatch_once(&onceToken, ^{
NSLog(@"1");
return;
});
}
else {
NSLog(@"2");
}
}
答案 3 :(得分:0)
return
语句从当前封闭范围返回,在您的情况下是块。您无法从外部封闭范围返回。
您可以使用一个简单的布尔标志来确定这是否是代码第一次执行,并使用串行调度队列来确保它是线程安全的。
类似的东西:
- (void)testGCD {
static dispatch_queue_t queue = dispatch_queue_create("com.example.MyQueue", NULL);
static bool firstRun = YES;
dispatch_sync(queue, ^{
if (firstRun) {
NSLog(@"1);
firstRun = NO;
} else {
NSLog(@"2");
}
});
}
通过使用串行调度队列,您可以确保无法同时更新firstRun
答案 4 :(得分:0)
Block就像一个完全独立的方法。其中的return
只会从块中返回。你真正需要的是:
- (void)testGCD {
static BOOL didTrigger = NO;
if(didTrigger) {
NSLog(@"2");
}
else {
didTrigger = YES;
NSLog(@"1");
}
}
您可能会尝试在您的案例中使用简单的锁,但我不确定在这种情况下会有多安全:
- (void)testGCD {
static dispatch_once_t onceToken;
static BOOL didInvokeOnceBlock = NO;
static BOOL didPassSkippedBlock = NO;
dispatch_once(&onceToken, ^{
NSLog(@"1");
didInvokeOnceBlock = YES;
});
if(didInvokeOnceBlock && didPassSkippedBlock) {
NSLog(@"2");
}
didPassSkippedBlock = YES;
}
但这仍然看起来在多线程时可能会有不稳定的结果。您可能需要以原子方式运行此结果才能使结果正确。我认为潜在的问题是:
didInvokeOnceBlock
didPassSkippedBlock
但跳过NSLog(@"2");
NSLog(@"2");