简体   繁体   English

初始化内部块后对象变为零

[英]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. buttonOnebuttonTwo不是属性。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM