Ephemera
Ephemera

Reputation: 8970

Attaching UIGestureRecognizers to encapsulated UIViews

I have an odd issue with a UITapGestureRecognizer whereby I always end up with a crash or exception thrown (unrecognised selector) when its action is to be invoked. I have used gesture recognisers before, but this time I am attaching it to a UIView which is a property of an NSObject (and I am using the object's methods to construct the view). The following is a minimal example of what I am doing:

MyObject.h:

#import <Foundation/Foundation.h>
@interface MyObject : NSObject
@property (nonatomic, strong) UIView *aView;
- (void)createViewWithFrame:(CGRect)frame;
@end

MyObject.m:

@interface MyObject ()
- (void)tapped:(id)sender; // Non-specific id type for brevity
@end

@implementation MyObject

- (void)tapped:(id)sender {
    NSLog(@"Tapped");
}

- (void)createViewWithFrame:(CGRect)frame {

    _aView = [[UIView alloc] initWithFrame:frame];
    self.aView.backgroundColor = [UIColor blueColor];
    self.aView.userInteractionEnabled = YES;
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
                                    initWithTarget:self
                                    action:@selector(tapped:)];

    [self.aView addGestureRecognizer:tap];

}

ViewController.m:

- (void)viewDidAppear:(BOOL)animated {

    [super viewDidAppear:animated];

    MyObject *obj = [[MyObject alloc] init];
    [obj createViewWithFrame:self.view.frame]; // Excuse poor frame - example only

    [self.view addSubview:obj.aView];
}

Then, when I tap on the view, the application crashes around here:

libobjc.A.dylib`objc_msgSend:
0x10e008c:  movl   8(%esp), %ecx
0x10e0090:  movl   4(%esp), %eax
0x10e0094:  testl  %eax, %eax
0x10e0096:  je     0x10e00e8                 ; objc_msgSend + 92
0x10e0098:  movl   (%eax), %edx
0x10e009a:  pushl  %edi
0x10e009b:  movl   8(%edx), %edi ; Thread 1: EXC_BAD_ACCESS (code=2, address=0x9)
0x10e009e:  pushl  %esi
0x10e009f:  movl   (%edi), %esi
0x10e00a1:  movl   %ecx, %edx

The exact crash-point varies, and I occasionally receive an invalid selector error. The NSLog, naturally, never happens. I have used gesture recognisers before (successfully), which leads me to believe the problem is in my setup/design. Can anyone explain why the gesture recognizer won't work properly in this case?

Upvotes: 0

Views: 187

Answers (1)

Thilina Chamath Hewagama
Thilina Chamath Hewagama

Reputation: 9040

The problem is with the scope of the MyObject, Declare the variable globally,

@property(nonatomic, strong) MyObject *obj;

in Your viewDidAppear, init and add the view

self.obj = [[MyObject alloc] init];
[self.obj createViewWithFrame:self.view.frame]; 
[self.view addSubview:self.obj.aView];

That's it.

Now it is working !!

What was the problem ?, *the scope of the MyObject obj ends with the viewDidAppear method. When a tap is recognized, It is looking for the object to fire the method given. But the object is not there.

Upvotes: 1

Related Questions