开发者

Supporting iOS versions prior to 4.0/3.2 and problems with NSClassFromString

I'm currently developing iPhone applications that -- for the time being -- need to be supported on versions prior to 4.x.

When I want to use something 4.x or 3.2 specific, I would use the usual approach of checking if a given class exists, i.e.:

if(NSClassFromString(@"SomeClass")) {
  // do stuff here
}

This mostly works, except when it doesn't. Let me explain:

Classes like:

  • UIMoviePlayerViewController (only available on 3.2+ according to the documentation)
  • UIGestureRecognizer subclasses (like UIPanGestureRecognizer; UITapGestureRecognizer, etc.)

Actually res开发者_StackOverflow中文版olve to valid classes, as if they were already available on private APIs on earlier versions. Is this the case, or am I missing something?

This is really bad, since the NSClassFromString() approach is actually recommended by Apple.

To be on the safe side, I'm currently checking the OS version instead of doing runtime checking for the classes existence.

Anyone else having this problem? Thanks.


Nope, you are not doing anything wrong, there are a number of private classes that were made public in 3.2/4.0. This would not be a big deal if they were just exposing existing functionality, but often the classes also have significantly altered functionality.

The only 100% viable thing to do is to test the version, even though that is generally frowned upon. Even testing for specific selectors may not be sufficient, since there is no guarantee that the selectors on old versions behave the same as the selectors on the version where the object was made public.


Checking the OS version is even better than using NSClassFromString(...) since some classes already exist in versions prior to 4.0/3.2 (as you mention). You can just use this way :)


For MPMoviePlayerViewController, I use [MPMoviePlayerController instancesRespondToSelector:@selector(view)]. They were added at the same time and are part of the same framework.

Sometimes Apple documents this; e.g. for UINib I think you're supposed to check [UINib respondsToSelector:@selector(nibWithNibName:bundle:)]. I can't remember where I read this.

I haven't actually come across the recommendation to use NSClassFromString(). I usually use something like [AVCaptureSession class], but you can equally just use [[[AVCaptureSession alloc] init...] autorelease]. Nonexistent weak-linked symbols become NULL at load time; this means the AVCaptureSession Class-object becomes Nil, and methods on nil do nothing and return nil.

If you're going to compare version numbers, a somewhat more reliable way is to compare against kCFCoreFoundationVersionNumber. I don't see one for 4.0 yet; kCFCoreFoundationVersionNumber_iPhoneOS_3_2 appears to be the highest one in the 4.0 headers.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜