I'm finishing iCloud feature for my app and can't solve one problem: Since I'm using some new 5.0 features like NSFileCoordinator, I can't build my app for 4.3 because of "dyld: Symbol not found: _OBJC_CLASS_$_NSFileCoordinator". How can I "untarget" some files (which have iCloud methods) for building 4.3 version? Thanks in advance!
6 Answers
Have a look at this.
Class cls = NSClassFromString (@"NSFileCoordinator");
if (cls) {
// Create an instance of the class and use it.
} else {
// Alternate code path to follow when the
// class is not available.
}
Also check this answer to see why
you should avoid relying on the version string as an indication of device or OS capabilities.
-
Thanks to all for replies. But that's what I need :) – Dmitry Zhukov Feb 14 '12 at 08:46
To just take them out of the source copilation:
- Click on your project file.
- Go to "Build Phases".
- Expand "Compile Sources".
- Select the file you dont want, and press the "-" button at the bottom of the section.
Or you can delete it from the project (just remove the reference rather than deleting the file), and it will remove it from this section as well.
Or you could create preprocessor macros to check to see if the user can run the functions
// System Versioning Preprocessor Macros
#define SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
/* Usage
if (SYSTEM_VERSION_LESS_THAN(@"4.0")) {
...
}
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"3.1.1")) {
...
}*/
With this, you can check to see what systen version the user is using and only build for 5.0, but put in functioning code for if it is a version less than 5.0.

- 7,206
- 1
- 28
- 46
I think it's better to turn off iCloud feature for 4.3 builds altogether. You can do that by check iOS version at runtime. In your particular case you could check for presence of NSFileCoordinator
class with NSClassFromString()
function, but I'm pretty sure there are more decent ways on the internet of accomplishing this.

- 48,927
- 17
- 132
- 168
You could make a new build target and set a compiler preprocessing Macro like NO_CLOUD and then use
#ifdef NO_CLOUD
... code here ...#else
... cloud code here ... #endif

- 9,280
- 2
- 42
- 58
-
The side effect of this solution is that he will end up with two different apps. – sch Feb 14 '12 at 08:21
-
yes indeed ... but he also explicitly asked for 'building a 4.3 version' ... :-) (ok, lame excuse) – TheEye Feb 14 '12 at 09:22
-
Just out of curiosity, would it be possible to distribute the two binaries as the same app in the App Store? Or would it be necessary to have two separate apps (one available only for iOS 5, and one available for both iOS 4.3 and iOS 5)? – sch Feb 14 '12 at 09:36
-
probably the second - it is indeed two different binaries, like you would do with a full and a lite version – TheEye Feb 14 '12 at 09:53
You have to weak link to the framwork's (when you add a framework to the project just set it as optional not required).
In the h file you have to import only if you have ios 5
#if defined(__IPHONE_5_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_5_0
#import <Twitter/Twitter.h>
#import <Accounts/Accounts.h>
#endif
and in the m file you have to try to create class from string and test to see if you have the class. And also test top see if the class responds to selectors.
Class TWTweetComposeViewControllerClass = NSClassFromString(@"TWTweetComposeViewController");
if (TWTweetComposeViewControllerClass != nil) {
if([TWTweetComposeViewControllerClass respondsToSelector:@selector(canSendTweet)]) {
UIViewController *twitterViewController = [[TWTweetComposeViewControllerClass alloc] init];
[twitterViewController performSelector:@selector(setInitialText:)
withObject:NSLocalizedString(@"TwitterMessage", @"")];
[twitterViewController performSelector:@selector(addURL:)
withObject:url];
[twitterViewController performSelector:@selector(addImage:)
withObject:[UIImage imageNamed:@"yourImage.png"]];
[self.navigationController presentModalViewController:twitterViewController animated:YES];
[twitterViewController release];
}
} else {
//do something else
}
My example is based on twitter engine you have to adapt it to your classes.

- 12,006
- 5
- 51
- 71
Build it with latest SDK (5.0). It will tun both 4.3 and 5.0
And you can check IOS version
if ([[UIDevice currentDevice] systemVersion] floatValue] >= 5.0f) {
// iCloud
} else {
// iCloudless
}

- 5,213
- 2
- 25
- 39