[英]Object becomes nil after init inside block
Here's my code: 这是我的代码:
__block UIButton buttonOne;
__block UIButton buttonTwo;
- (UIView *)addressOptionView
{
if (!_addressOptionView) {
_addressOptionView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.frame), addressButtonArray.count * BasedAdditionForSegment)];
void (^setupButton)(UIButton *, NSString *, NSInteger) = ^
void (UIButton *button, NSString *title, NSInteger idx) {
if (!button)
button = [[UIButton alloc] init];
button.frame = ({
CGRect frame = _addressOptionView.bounds;
frame.origin.x += 20;
frame.size.width -= 40;
frame.origin.y = idx * BasedAdditionForSegment;
frame.size.height = BasedAdditionForSegment;
frame;
});
[button setTitle:title forState:UIControlStateNormal];
};
setupButton(buttonOne, addressButtonArray[0], 0);
setupButton(buttonTwo, addressButtonArray[1], 1);
DebugLog(@"%@", buttonOne);
[_addressOptionView addSubview:buttonOne];
[_addressOptionView addSubview:buttonTwo];
}
return _addressOptionView;
}
buttonOne
and buttonTwo
is not properties. buttonOne
和buttonTwo
不是属性。
After I call addressOptionView getter
, these two buttons are deallocated immediately, thus they don't show up in the view (I guess, nil when NSLog
). 在我调用
addressOptionView getter
,这两个按钮会立即被释放,因此它们不会显示在视图中(我想在NSLog
时为nil)。
I changed the setupButton
block to @property
and it doesn't work either. 我将
setupButton
块更改为@property
,它也不起作用。 Changing two button to @property
doesn't work too. 将两个按钮更改为
@property
也不起作用。
However, when I change the setupButton
block to 但是,当我将
setupButton
块更改为
UIButton * (^setupButton)(NSString *, NSInteger)
Two buttons do show up, but I cannot access them later in other methods ( nil
already). 确实出现了两个按钮,但是以后我无法以其他方法访问它们(已经为
nil
)。
Can somebody give me a brief explanation about what do I do wrong ? 有人可以简要说明我做错了什么吗? How do I make it work ?
我该如何运作? Thanks.
谢谢。
@implementation SomeObject {
// do not make these __block types
UIButton* _buttonOne;
UIButton* _buttonTwo;
}
- (UIView *)addressOptionView
{
// most of method removed for brevity, see question
void (^setupButton)(UIButton*__autoreleasing*, NSString *, NSInteger) = ^
void (UIButton*__autoreleasing*button, NSString *title, NSInteger idx) {
NSAssert( button, @"Must not pass nil reference as button" );
UIButton* localButton = *button;
if (!localButton) {
// continue to work on the more convenient localButton, but make sure
// that the button reference is written to the ivar...
localButton = *button = [UIButton buttonWithType:UIButtonTypeCustom];
}
// other button setup clipped
};
// compiler will generate strong stack-allocated temporary variable here
// to deal with autoreleasing assignment, but make sure ivars are not
// __block class
setupButton(&_buttonOne, addressButtonArray[0], 0);
setupButton(&_buttonTwo, addressButtonArray[1], 1);
DebugLog(@"%@", _buttonOne);
[_addressOptionView addSubview:_buttonOne];
[_addressOptionView addSubview:_buttonTwo];
// top-most branch was clipped for this example
return _addressOptionView;
}
This line is the problem... 这行是问题所在...
button = [[UIButton alloc] init];
Once you do that, the copy of the reference to your button that you passed into your block is now pointing to a different location in memory. 完成此操作后,传递给块的按钮引用的副本现在指向内存中的其他位置。 This does not change where the original button reference is pointing as you are only changing where the copied button reference is pointing.
这不会改变其中原始按钮引用指向你在那里复制的按钮引用指向只更改。 Remember, objective-c is pass by value!
请记住,目标-c是价值传递!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.