【问题标题】:Performing selector on UILabel generates crash?在 UILabel 上执行选择器会导致崩溃?
【发布时间】:2016-03-22 18:50:54
【问题描述】:

我读到 UILabel 并不是为了响应触摸事件,我可以只使用 UIButton。但是,无论如何我都必须继承 UILabel 以覆盖另一个方法,所以我想我不妨使用标签来尽量减少对代码的更改。

如何让我的标签响应触摸事件?显示的代码和错误如下。

UILabel *tempLabel = [[UILabel alloc] initWithFrame:CGRectMake(startingPoint, 5, 10, 22)];
    tempLabel.text = equationText;
    tempLabel.font = [UIFont systemFontOfSize:13];
   [tempLabel sizeToFit];
    [view addSubview:tempLabel];
    [tempLabel addTarget:self action:@selector(updateLabel:) forControlEvents:UIControlEventTouchUpInside]; // UNRECOGNIZED SELECTOR SENT TO INSTANCE

【问题讨论】:

    标签: objective-c ios uilabel selector


    【解决方案1】:

    由于UILabel 不是控件,因此您无法发送-addTarget:action:forControlEvents: 消息。您必须从您的应用程序中删除该行,因为您的标签不是控件,并且永远不会响应该消息。相反,如果您想使用您的标签,您可以将其设置为交互式并向其添加手势识别器:

    // label setup code omitted
    UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(updateLabel:)];
    [tempLabel setUserInteractionEnabled:YES];
    [tempLabel addGestureRecognizer:tap];
    [tap release]; // if not using ARC
    

    手势识别器的回调将传递触发它的手势识别器的实例,而不是像操作消息那样的控件。要获取触发事件的标签实例,请使用-view 向传入的手势识别器发送消息。因此,如果您的 updateLabel: 方法可能实现如下:

    - (void)updateLabel:(UIGestureRecognizer*)recognizer
    {
      // Only respond if we're in the ended state (similar to touchupinside)
      if( [recognizer state] == UIGestureRecognizerStateEnded ) {
        // the label that was tapped
        UILabel* label = (UILabel*)[recognizer view];
    
        // do things with your label
      }
    }
    

    此外,手势识别器将调用具有多种状态的动作方法,类似于-touchesBegan:... 系列方法中的那些。您应该检查您是否只在识别器处于适当状态时才提交工作。对于您的简单点击手势识别器,您可能只想在识别器处于UIGestureRecognizerStateEnded 状态时工作(参见上面的示例)。有关手势识别器的更多信息,请参阅UIGestureRecognizer 的文档。

    【讨论】:

      【解决方案2】:

      //创建标签

      _label = [[UILabel alloc] initWithFrame:CGRectMake(self.view.center.x-75,self.view.frame.size.height-60, 150, 50)];

      _label.backgroundColor = [UIColor clearColor];
      _label.textColor=[UIColor whiteColor];
      _label.text = @"Forgot password ?";
      UITapGestureRecognizer *recongniser = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapAction)];//ADD ACTION TO LABEL
      [_label setUserInteractionEnabled:YES];
      [_label addGestureRecognizer:recongniser];
      

      //从一个视图导航到另一个视图

      -(void) tapAction //添加到标签选择器的方法

      {

      _forgotviewController=[[ForgotPassword alloc]init];
      [self.navigationController pushViewController:self.forgotviewController animated:YES];
      

      }

      【讨论】:

        【解决方案3】:

        这里最聪明的做法是使用 UIButton 来做你想做的事情。

        但如果你真的想继承 UILabel,请确保将 userInteractionEnabled 设置为 YES。

        The documentation says:

        默认情况下,新标签对象配置为忽略用户事件。 如果要在 UILabel 的自定义子类中处理事件,则必须 将 userInteractionEnabled 属性的值显式更改为 初始化对象后是。

        addTarget: action: forControlEvents: 不起作用,因为UILabel 不是UIControl 的后代。您可以通过在您的子类中实现 UIResponder 的 touchesBegan:withEvent: 方法来捕捉您的事件。

        【讨论】:

        • 更改了userInteractionEnabled 并添加了一个空的touchesBegan,但应用程序仍然崩溃
        • 在另一个 SO 问题上,有人写道“您必须从 UILabel 派生并实现 UIResponder 调用以进行触摸处理。”我不完全确定该怎么做
        • @MahirE 该声明具有误导性,因为 所有 视图都继承自 UIResponder。另一方面,并​​非所有视图都继承自 UIControl
        【解决方案4】:

        这里是 UILabel tap

        的 swift 2.1 版本
        let label = UILabel(frameSize)
        
        let gesture = UITapGestureRecognizer(target: self, action: "labelTapped:")
        labelHaveAccount.userInteractionEnabled = true
        labelHaveAccount.addGestureRecognizer(gesture)
        
        func labelTapped(gesture:UIGestureRecognizer!){
        //lable tapped
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-12-15
          • 2011-10-01
          • 2015-01-13
          • 1970-01-01
          相关资源
          最近更新 更多