【问题标题】:understanding uibutton target self superview了解uibutton目标自我监督
【发布时间】:2014-11-15 15:02:35
【问题描述】:

有人可以向我解释一下这个例子中的 uibutton 目标功能吗:

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

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

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

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

感谢您的帮助!

【问题讨论】:

  • 你确定蓝色按钮的动作被执行了吗?它不应该作为您添加的目标是nil
  • 100% 确定。创建一个项目,粘贴代码并自己尝试。奇怪的东西他...

标签: ios objective-c uiview uibutton


【解决方案1】:

您确实为initWithFrameMethod 中的蓝色按钮添加了nil 目标。根据Apple的Event Handling Guide,当您添加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

【讨论】:

  • 我认为这是一个有趣的案例...有人可以告诉 why [self superview] 在用作 target 时是 nil initWithFrame:?视图控制器的视图应该在那个时间点被实例化,因为 MySpecialView 是在视图控制器的 viewDidLoad 中创建的
  • initWithFrame 在 `MySpecialView 作为子视图添加到控制器视图之前调用。
  • 啊抱歉,当然是 nil,因为视图还没有被添加到视图控制器的视图中!
  • @nburk,因为您首先创建了要添加的对象(在本例中为 uiview),并且只有当返回 self 发生时,它才会添加到 superview。
【解决方案2】:

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

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

【讨论】:

  • 很好解释!您需要确保您的 target 不是视图控制器的视图,而是视图控制器本身!但是,对于您的情况,delegate 模式听起来更合适。
  • 好的,谢谢您的留言。我知道如果我添加类似主视图之类的东西并在其上放置一个视图,则 [self superview] 会起作用。当我为其他东西下载一个示例项目时,我遇到了这个问题,并对它的工作感到惊讶。所以我的目标不是帮助我进行 uiview 之间的通信,我知道它是如何工作的,但我想了解 action 是如何到达 ViewController 并执行方法的。
猜你喜欢
  • 2013-02-28
  • 2017-09-04
  • 2020-09-21
  • 2017-06-15
  • 2014-04-20
  • 2010-10-15
  • 2019-09-28
  • 2017-11-10
  • 2017-11-29
相关资源
最近更新 更多