简体   繁体   中英

understanding uibutton target self superview

Can someone please explain to me the uibutton target functionality from this example:

I have a ViewController. I add a uiview with two buttons to this viewcontroller. One button is crated in the init and the other one is created by a method 'addSecondButton'. Both buttons have the same action on [self superview] target which is the ViewController. The code:

ViewController.m

- (void)viewDidLoad {
    [super viewDidLoad];

    MySpecialView *myspecialview = [[MySpecialView alloc] initWithFrame:self.view.frame];
    [self.view addSubview:myspecialview];

    [myspecialview addSecondButton];
}

- (void)specialMethod { NSLog(@"right here!"); }

MySpecialView.m

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 30, frame.size.width, 50)];
        [button addTarget:[self superview] action:@selector(specialMethod) forControlEvents:UIControlEventTouchUpInside];
        button.backgroundColor = [UIColor blueColor];
        [self addSubview:button];
    }
    return self;
}

- (void)addSecondButton {
    UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 90, self.frame.size.width, 50)];
    [button addTarget:[self superview] action:@selector(specialMethod) forControlEvents:UIControlEventTouchUpInside];
    button.backgroundColor = [UIColor redColor];
    [self addSubview:button];
}

So when tapping the blue button which is created in the init, specialMethod does execute. When pressing the red one which is added after the init, the app crashes with the warning - unknow selector for uiview.

What I really don't understand is when I NSLog [self superview] in the init, it is null, because the object is not yet created and returned to the superview, but the action does get executed for some reason.

Thanks for the help!

You have indeed added a nil target for the blue button in initWithFrameMethod . According to the Apple's Event Handling Guide , when you add a nil target, the message ( specialMethod in your case) will be passed through the responder chain:

When the user manipulates a control, such as a button or switch, and the target for the action method is nil, the message is sent through a chain of responders starting with the control view.

As your ViewController is a part of the responder chain, it will receive this message and call its specialMethod .

[self superview] is a pointer to ViewController's view, not ViewController itself. The selector you are defining as the action for the button should target the instance of ViewController, not the ViewController's view since you have the method specialMethod defined in ViewController. If you really wanted to use [self superview] as the target for the action, then you'll need to subclass UIView, implement specialMethod and set that new UIView subclass as the view of the view controller (not a subview). This way, [self superview] will refer to a class that actually has the selector specified on the target.

I didn't actually try your code sample, but it's so obviously wrong, if it does work, it's coincidence and shouldn't be relied upon.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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