3

I'm trying to use NSClassFromString to prevent a block of code from running on pre iOS 3.2 devices. The code block in question is as follows:

if (NSClassFromString(@"UITapGestureRecognizer"))
{
    UITapGestureRecognizer *tap = [[[UITapGestureRecognizer alloc] initWithTarget:self
                                                                          action:@selector(dismissKeyboard)] autorelease];
    [tap setCancelsTouchesInView:NO];
    [[self view] addGestureRecognizer:tap];
}

I'm doing this because Apple's documentation states that UITapGestureRecognizer is incompatable with pre 3.2 installations. https://developer.apple.com/library/ios/#documentation/uikit/reference/UITapGestureRecognizer_Class/Reference/Reference.html

I originally thought that using NSClassFromString would return nil when I ran it on this device, but it does not. The statement is true and the code executes. (An interesting note, the code sort of works on a pre 3.2 installation.)

Anyway, I'd like to know why NSClassFromString is NOT returning nil, and is there anything I can do otherwise to accomplish what I'm trying to do?

enter image description here

Zoe
  • 27,060
  • 21
  • 118
  • 148
Joey
  • 1,075
  • 8
  • 8

2 Answers2

8

From the docs

Usage Special Considerations

To determine whether a class is available at runtime in a given iOS release, you typically check whether the class is nil. Unfortunately, this test is not cleanly accurate for UIGestureRecognizer. Although this class was publicly available starting with iOS 3.2, it was in development a short period prior to that. Although the class exists in an earlier release, use of it and other gesture-recognizer classes are not supported in that earlier release. You should not attempt to use instances of those classes.

To determine at runtime whether you can use gesture recognizers in your application, test whether the class exists and, if it does, allocate an instance and see check if it responds to the selector locationInView:. This method was not added to the class until iOS 3.2. The code might look like the following:

UIGestureRecognizer *gestureRecognizer = [[UIGestureRecognizer alloc] initWithTarget:self action:@selector(myAction:)];
 
if (![gestureRecognizer respondsToSelector:@selector(locationInView:)]) {
    [gestureRecognizer release];
    gestureRecognizer = nil;
}
// do something else if gestureRecognizer is nil
Community
  • 1
  • 1
vikingosegundo
  • 52,040
  • 14
  • 137
  • 178
  • Yes, I think Apple also mentions this in one of the WWDC videos as a special case to look out for. Other people have hit this exact same issue before: http://www.nanoant.com/apple/wanna-be-3-x-compatible-not-so-simple – Brad Larson Feb 03 '12 at 20:10
2

What is probably happening is that UITapGestureRecognizer exists but is just not public in 3.1.3. I've had luck in the past with checking for UISplitViewController.

Carl Veazey
  • 18,392
  • 8
  • 66
  • 81