ARC 和块语法 EXC_BAD_ACCESS

ARC and Block syntax EXC_BAD_ACCESS

如果这个属性是'strong',就没有问题。但是,如果这个 属性 是 'weak',那么我会收到错误 EXC_BAD_ACCESS。

@property (weak, nonatomic) void(^pickerCompletion)(NSDate *date);    

-(void)textFieldDidEndEditing:(UITextField *)textField {
    if (self.pickerCompletion) self.pickerCompletion(self.date);
}

我正在使用 if 语句来检查 属性 是否为 nil,那么这里的问题是什么?

如果 ARC 清除了这个指针,那么我希望 if 语句求值为 false 并且不执行该块。

@property (strong, nonatomic) void(^pickerCompletion)(NSDate *date);    

如果属性是strong,编译器会自动复制块。 pickerCompletion 拥有复制块(堆块)的所有权。

@property (weak, nonatomic) void(^pickerCompletion)(NSDate *date);    

但是如果属性是weak,编译器什么都不做,只是把指针值赋给变量。如果指针是 Stack Block(只是普通的块文字),指针值永远不会被 ARC 填零。难道你没有从编译器那里得到警告信息吗?

warning: assigning block literal to a weak property; object will be
  released after assignment

此外还有竞争条件。

if (self.pickerCompletion) self.pickerCompletion(self.date);
在多线程环境中,

self.pickerCompletion 可以在 if (self.pickerCompletion) 之后的 self.pickerCompletion(self.date) 之前补零。使用临时 __strong 变量来安全访问弱对象。

void(^pickerCompletion)(NSDate *date) = self.pickerCompletion;
if (pickerCompletion) pickerCompletion(self.date);