10

I have printed a UITableviewCell's gesture in – tableView:didSelectRowAtIndexPath method in NSLog as

<UIScrollViewPanGestureRecognizer: 0x11e92080; state = Possible; cancelsTouchesInView = NO; delaysTouchesEnded = NO; view = <UITableViewCellScrollView 0x11e94bf0>; target= <(action=handlePan:, target=<UITableViewCellScrollView 0x11e94bf0>)>> 

and I have assigned this UIScrollViewPanGestureRecognizer to a UIGestureRecognizer to access the properties of it as follows,

 UIGestureRecognizer *myGes=[temp.gestureRecognizers objectAtIndex:1];

I'm able to access all properties of 'myGes' as

 myGes.state;
 myGes.cancelsTouchesInView;
 myGes.delaysTouchesEnded;
 myGes.view;

Except one property named as target.

Is there any possibility to access that property? because i need to perform that action.

Any comments or suggestions would be appreciated.

Thank you in advance.

Ashok
  • 5,585
  • 5
  • 52
  • 80

3 Answers3

9

There is a way to gain access to the property target, but I'm not sure that this method will pass the Apple approval process.

NSMutableArray *targets = [myGes valueForKeyPath:@"_targets"];
id targetContainer = targets[0];//get first target for example
id targetOfMyGes = [targetContainer valueForKeyPath:@"_target"];
NSLog(@"%@", targetOfMyGes );//you can see reference for target object

Thanks neilco - his answer help create solution.

Note: the exact class of the object targetOfMyGes need to define yourself. By default it id - suitable for any object class.

Community
  • 1
  • 1
Ruslan Soldatenko
  • 1,718
  • 17
  • 25
  • +1 Thanks..@RuslanSoldatenko..Means it's like accessing private properties or private methods? – Ashok Nov 27 '13 at 12:30
  • Yes, access to private properties or private methods is possible by KVC - Key Value Coding. But I not shure what it encouraged by Apple. – Ruslan Soldatenko Nov 27 '13 at 12:36
  • @Ashok Kumar .S small addition: array `targets` contains hidden class objects `UIGestureRecognizerTarget` description of which can be found here: https://github.com/rpetrich/iphoneheaders/blob/master/UIKit/UIGestureRecognizerTarget.h – Ruslan Soldatenko Nov 27 '13 at 12:48
  • @RuslanSoldatenko..but while accessing the action as id action = [targetContainer valueForKeyPath:@"_action"]; the app is crashing. – Ashok Nov 29 '13 at 06:25
  • @Ashok Kumar .S `_action` is selector. Try use `SEL action = [targetContainer valueForKeyPath:@"_action"];` – Ruslan Soldatenko Nov 29 '13 at 11:39
  • i tried that too... SEL myAction=[targetContainer valueForKeyPath:@"_action"]; still crashing. Tried in this way.. SEL myAction=(SEL)[targetContainer valueForKeyPath:@"_action"]; But still crashing.. – Ashok Nov 30 '13 at 07:01
  • @Ashok Kumar .S Unfortunately, another way to access to `_action` I do not know. – Ruslan Soldatenko Nov 30 '13 at 20:08
  • @RuslanSoldatenko..No problem..I'll try in another approach..Really Thanks for you.. – Ashok Dec 02 '13 at 06:40
  • 1
    The underscores are unnecessary. KVC automatically searches instance variables starting with an underscore, so `@"targets"` and `@"target"` are preferable. Also, you can use `valueforKey:` instead of `valueForKeyPath:` since you're just using a single key, not a key path. As for the selector, KVC doesn't work for C pointer types. You would have to use runtime functions to access it: `SEL action = ((SEL (*)(id, const char*))object_getIvar)(targetContainer, class_getInstanceVariable([targetContainer class], "_action"))` – user102008 Apr 17 '14 at 02:36
  • This is a very dangerous practice that can break your app anytime apple releases an update. – TigerCoding Dec 29 '15 at 20:13
  • @user102008 The underscore is made by apple to show you that you are not allowed to access it, or in their own word "Names of most private methods in the Cocoa frameworks have an underscore prefix (for example, _fooData ) to mark them as private. " https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingMethods.html –  Aug 23 '17 at 23:43
2

UIGestureRecognizer internally maintains an array of targets. There is no public access to this array.

neilco
  • 7,964
  • 2
  • 36
  • 41
-3

I have a different solution to this which has worked for me. This is more of a design change... you cannot access the target from the captured gesture. So instead keep a reference to the object when the touch down happened and before the pan began.

@property (nonatomic, strong) UIButton *myTouchedButton; // reference to button

(void)init
{
    ...
    [card.button addTarget:self action:@selector(cardTouchDownInside:) forControlEvents:UIControlEventTouchDown];
    ...
}

-(void)cardTouchDownInside:(id)sender
{
    NSLog(@"touch down on object");
    self.myTouchedButton = (UIButton*)sender;
}
mihai
  • 4,184
  • 3
  • 26
  • 27