了解UIBUTTON目标自我超级视图



有人可以向我解释此示例中的uibutton目标功能吗:

我有一个视图控制器。我向此视图控制器添加了一个带有两个按钮的 uiview。一个按钮在 init 中装箱,另一个由方法"addSecondButton"创建。这两个按钮在[self superview]目标(即ViewController)上具有相同的操作。代码:

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];
}

因此,当点击在初始化中创建的蓝色按钮时,specialMethod 确实会执行。当按下在初始化后添加的红色时,应用程序崩溃并显示警告 - uiview 的未知选择器。

我真正不明白的是,当我在 init 中 NSLog [self superview] 时,它是空的,因为对象尚未创建并返回到超级视图,但由于某种原因,该操作确实被执行了。

感谢您的帮助!

您确实为 initWithFrameMethod 中的蓝色按钮添加了nil目标。根据 Apple 的事件处理指南,当您添加nil目标时,消息(在您的情况下specialMethod)将通过响应器链传递:

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.

由于您的ViewController是响应程序链的一部分,因此它将接收此消息并调用其specialMethod

[self superview]是指向ViewController视图的指针,而不是ViewController本身。 您定义为按钮操作的选择器应针对 ViewController 的实例,而不是 ViewController 的视图,因为您在 ViewController 中定义了specialMethod方法。 如果您确实想使用 [self superview] 作为操作的目标,则需要对 UIView 进行子类化,实现specialMethod并将新的 UIView 子类设置为视图控制器的视图(而不是子视图)。 这样,[self superview]将引用一个类,该类实际上在目标上指定了选择器。

我实际上并没有尝试过您的代码示例,但它显然是错误的,如果它确实有效,那是巧合,不应该依赖。

最新更新