0
votes

If this property is 'strong', there is no problem. However, if this property is 'weak', then I receive error EXC_BAD_ACCESS.

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

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

I am using an if statement to check the property is nil or not, so what is the issue here ?

If ARC cleans this pointer, then I want the if statement to evaluate to false and not execute the block.

1
i think thats not the right way to check nill - Teja Nandamuri
why you want to use weak and nonatomic ? Apple suggest to use copy for blocks - Teja Nandamuri
I'm going to guess that you're setting this property to point to a block that is still on the stack. Therefore it isn't yet reference counted, and the weak pointer won't be zeroed when it moves out of scope, because, technically, it was never released in the first place. As TT_77 observes, block properties should always be copy, though I think the nonatomic is perfectly fine. Copy tells the runtime "This needs to move from the stack to the heap so it can persist past the current stack frame where it was assigned." - Ben Pious
Want to make that an official answer? I will accept it. Just found what your talking about in the Apple docs. developer.apple.com/library/ios/documentation/Cocoa/Conceptual/… - user1951992

1 Answers

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

If the property is strong, the compiler automatically copies the block. pickerCompletion has the ownership of the copied block(Heap Block).

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

But if the property is weak, the compiler does nothing, just put the pointer value to the variable. And if the pointer is Stack Block (just ordinary block literal), the pointer value is never zero-filled by ARC. Didn't you get a warning message from the compiler like that?

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

Besides there is a race condition.

if (self.pickerCompletion) self.pickerCompletion(self.date);

self.pickerCompletion could be zero-filled before self.pickerCompletion(self.date) after if (self.pickerCompletion) in multithreading environment. Use temporary __strong variable for accessing the weak object safely.

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