Objective-C - 为什么 UITapGestureRecognizer 会导致应用程序崩溃?

Objective-C - why the UITapGestureRecognizer crashing the app?

我将动态 UIView 作为 Array droplet。当点击那些随机的 UIView 对象时,我需要在那个特定的 droplet 上做 activity。所以当我触发这个 UITapGestureRecognizer *gesRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(ui_view_array_clicked)]; [ui_view addGestureRecognizer:gesRecognizer]; 应用程序崩溃时。

可能出了什么问题?我也尝试过 @selector(ui_view_array_clicked:i) 但在这两种情况下,只要我单击 gesRecognizer

附带的任何一个 UIView,就会崩溃

错误:

2017-03-14 02:16:33.322 testing[80405:5647302] -[ViewController ui_view_array_clicked]: unrecognized selector sent to instance 0x7f9733d01f70
2017-03-14 02:16:33.337 testing[80405:5647302] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[ViewController ui_view_array_clicked]: unrecognized selector sent to instance 0x7f9733d01f70'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010fc85d4b __exceptionPreprocess + 171
    1   libobjc.A.dylib                     0x000000010f6e721e objc_exception_throw + 48
    2   CoreFoundation                      0x000000010fcf5f04 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
    3   CoreFoundation                      0x000000010fc0b005 ___forwarding___ + 1013
    4   CoreFoundation                      0x000000010fc0ab88 _CF_forwarding_prep_0 + 120
    5   UIKit                               0x00000001105e5409 -[UIGestureRecognizerTarget _sendActionWithGestureRecognizer:] + 57
    6   UIKit                               0x00000001105ed1a8 _UIGestureRecognizerSendTargetActions + 109
    7   UIKit                               0x00000001105eac77 _UIGestureRecognizerSendActions + 227
    8   UIKit                               0x00000001105e9f03 -[UIGestureRecognizer _updateGestureWithEvent:buttonEvent:] + 891
    9   UIKit                               0x00000001105d5f7e _UIGestureEnvironmentUpdate + 1395
    10  UIKit                               0x00000001105d59c3 -[UIGestureEnvironment _deliverEvent:toGestureRecognizers:usingBlock:] + 521
    11  UIKit                               0x00000001105d4ba6 -[UIGestureEnvironment _updateGesturesForEvent:window:] + 286
    12  UIKit                               0x000000011011ac1d -[UIWindow sendEvent:] + 3989
    13  UIKit                               0x00000001100c79ab -[UIApplication sendEvent:] + 371
    14  UIKit                               0x00000001108b472d __dispatchPreprocessedEventFromEventQueue + 3248
    15  UIKit                               0x00000001108ad463 __handleEventQueue + 4879
    16  CoreFoundation                      0x000000010fc2a761 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    17  CoreFoundation                      0x000000010fc0f98c __CFRunLoopDoSources0 + 556
    18  CoreFoundation                      0x000000010fc0ee76 __CFRunLoopRun + 918
    19  CoreFoundation                      0x000000010fc0e884 CFRunLoopRunSpecific + 420
    20  GraphicsServices                    0x0000000113a71a6f GSEventRunModal + 161
    21  UIKit                               0x00000001100a9c68 UIApplicationMain + 159
    22  testing                             0x000000010f11053f main + 111
    23  libdyld.dylib                       0x0000000112ae768d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

代码:

#import "ViewController.h"
@interface ViewController ()

@property (copy, nonatomic) NSMutableArray *randomSelection;
@property (assign, nonatomic) NSInteger phone_height;
@property (assign, nonatomic) NSInteger phone_width;
-(void)ui_view_array_clicked:(int)array_id;
@end

@implementation ViewController

-(void)ui_button_submit:(UIButton*)sender {
  int phone_height  =  self.view.frame.size.height;
  int phone_width  =  self.view.frame.size.width;
  self.phone_height = phone_height;
  self.phone_width = phone_width;

  NSMutableArray *randomSelection = [[NSMutableArray alloc] init];

  // Set - UIView
  int j = 0;
  int k = 0;
  int l = 0;
  for (int i = 0;  i <= 50; i++) {
    int col = floor(self.phone_width/50);
    int logic = floor(i/col);

    int xx = (i * 50);
    if (logic == 1) {
      xx = (j * 50);
      j++;
    }
    else if (logic == 2 ) {
      xx = (k * 50);
      k++;
    }
    else if (logic == 3 ) {
      xx = (l * 50);
      l++;
    }


    NSLog(@">>> %d %d %d %d" , xx ,  logic  ,  i, j);
    UIView *ui_view = [[UIView alloc] initWithFrame:CGRectMake(xx, 50 * logic , 50,50)];
    [randomSelection addObject:ui_view];
    UITapGestureRecognizer *gesRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(ui_view_array_clicked)];
    [ui_view addGestureRecognizer:gesRecognizer];


    if(i%2==0) {
      ui_view.backgroundColor = [UIColor blueColor];
    }
    else {
      ui_view.backgroundColor = [UIColor redColor];
    }

    [self.view addSubview:ui_view];

  }

  UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Made 50 RED UIView"
                                                                 message:@"Will make them Black now" preferredStyle:UIAlertControllerStyleAlert];
  UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){
    for (int i = 0; i <= 50; i++) {
      NSLog(@"<<< %d" , i);
      UIView *test = [randomSelection objectAtIndex:i];
        //test.backgroundColor = [UIColor blackColor];
      if(i%2==0) {
        test.backgroundColor = [UIColor redColor];
      }
      else {
        test.backgroundColor = [UIColor blueColor];
      }

    }
  }];
  [alert addAction:defaultAction];
  [self presentViewController:alert animated:YES completion:nil];

}

-(void)ui_view_array_clicked:(int)array_id {
  NSLog(@">>> clicking: %d", array_id);

}

-(void)ui_button {
  self.view.backgroundColor = [UIColor blackColor];
  UIButton *but = [[UIButton alloc] init];
  [but setTitle:@"--- Add ---" forState:UIControlStateNormal];
  [but setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
  [but addTarget:self action:@selector(ui_button_submit:)
        forControlEvents:UIControlEventTouchUpInside];

  int startHeight = 167;
  int frameHeight = self.view.frame.size.height - startHeight;
  [but setFrame:CGRectMake(0, startHeight, 320, frameHeight)];

  [but setTranslatesAutoresizingMaskIntoConstraints:false];
  [but setImage:[UIImage imageNamed:@"Image"] forState:UIControlStateNormal];
  [self.view addSubview:but];


  NSDictionary *viewsDict = @{@"button" : but};
  [self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"V:[button]-0-|"
                           options:0 metrics:nil views:viewsDict]];

  NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:but
      attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual
      toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0
      constant:0];
  constraint.active = true;
  [self.view addConstraint:constraint];
  [self.view layoutIfNeeded];

}

- (void)viewDidLoad {
  [super viewDidLoad];
  [self ui_button];
}


@end

你应该改变初始化方法

UITapGestureRecognizer *gesRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(ui_view_array_clicked:)];

函数应声明为

- (void) ui_view_array_clicked: (UITapGestureRecognizer *)recognizer
{
   // Do something
}

您的手势识别器的动作方法是

ui_view_array_clicked

但是你在视图控制器中没有相应的方法。

-(void)ui_view_array_clicked:(int)array_id  

但这是不同的方法/签名。

另外

  • gestureRecognizer 目标的签名不采用任何参数或采用单个参数。单参数版本的参数需要是特定类型的:即发送消息的手势识别器。

因此以下任一模式都有效:

UITapGestureRecognizer *gesRecognizer = 
    [[UITapGestureRecognizer alloc] 
              initWithTarget:self 
                      action:@selector(gestureSelector)];  
 //selector

- (void)gestureSelector

或...

UITapGestureRecognizer *gesRecognizer = 
    [[UITapGestureRecognizer alloc] 
              initWithTarget:self 
                      action:@selector(gestureSelector:)];  
 //selector

- (void)gestureSelector:(UITapGestureRecognizer*)gestureRecognizer

还有...

使用 snake_case 对于 ObjectiveC 来说是非常不习惯的...推荐使用 camelCaseAtAllTimes,尤其是对于方法。

你应该试试下面的答案

UIView *ui_view = [[UIView alloc] initWithFrame:CGRectMake(xx, 50 * logic , 50,50)];
[randomSelection addObject:ui_view];
UITapGestureRecognizer *gesRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(ui_view_array_clicked:)];
[ui_view addGestureRecognizer:gesRecognizer];

这将在您的 view

上设置点击手势

在您的方法中访问点击的 view

- (void)gestureSelector:(UITapGestureRecognizer*)gestureRecognizer{
    UIView *your_tapped_view = gestureRecognizer.view;
}

使用此代码。

不要忘记在手势方法声明中添加 :