如何在GCD块中返回当前方法?

时间:2018-05-17 08:11:29

标签: ios objective-c block

这是我的代码:

return

控制台打印1 2。

我想要的只是第一次打印1。我想也许hero-details没有从方法返回,而是从块中返回。

有什么方法可以从这个GCD块中的当前方法返回?

5 个答案:

答案 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;
}

但这仍然看起来在多线程时可能会有不稳定的结果。您可能需要以原子方式运行此结果才能使结果正确。我认为潜在的问题是:

  • 线程A和线程B开始执行相同的方法。
  • 主题A收集令牌并解锁didInvokeOnceBlock
  • 主题B跳过阻止并解锁didPassSkippedBlock但跳过NSLog(@"2");
  • 线程A调用NSLog(@"2");