Reputation: 79
I am trying to add UIRefreshControl for IOS 6.
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"6.0")) {
UIRefreshControl *refresh = [[UIRefreshControl alloc] init];
refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"Pull to Refresh"];
[refresh addTarget:self action:@selector(refreshView:)
forControlEvents:UIControlEventValueChanged];
self.refreshControl = refresh;
}
and
if (NSClassFromString(@"UIRefreshControl") != Nil) {
UIRefreshControl *refresh = [[UIRefreshControl alloc] init];
refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"Pull to Refresh"];
[refresh addTarget:self action:@selector(refreshView:)
forControlEvents:UIControlEventValueChanged];
self.refreshControl = refresh;
}
but getting the error
dyld: Symbol not found: _OBJC_CLASS_$_UIRefreshControl
Referenced from: /Users/office/Library/Application Support/iPhone Simulator/4.3.2/Applications/DD532E42-77F9-471C-AA48-7F9EAE9268C6/Verizon.app/Verizon
Expected in: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/i PhoneSimulator4.3.sdk/System/Library/Frameworks/UIKit.framework/UIKit
i am using IOS 6 SDK and running on iPhone 4.3 Simulator.
When i remove the code
UIRefreshControl *refresh = [[UIRefreshControl alloc] init];
refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"Pull to Refresh"];
[refresh addTarget:self action:@selector(refreshView:)
forControlEvents:UIControlEventValueChanged];
self.refreshControl = refresh;
everything works for iPhone 4.3 Simulator. Interestingly code inside
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"6.0")) { }
never gets called when on iPhone 4.3 Simulator, not sure why the error. Please Help!!
Upvotes: 1
Views: 1807
Reputation: 34912
Definitely go with the second style, i.e.:
if (NSClassFromString(@"UIRefreshControl") != nil) {
...
}
As for the error you are getting, you should be able to stop that by setting UIKit to "Optional" within the "Link binary with libraries" section of the project's "Build Phases" settings.
It should mark it as optional for you as it notices you're using a class that's only available in iOS 6, but looks like it's not in your case for some reason.
Upvotes: 1
Reputation:
Nevermind the code doesn't get called - when the application loads, the dynamic linker needs to resolve all the symbols in the dynamic libraries the app's binary is linked to. In iOS 4.3, the UIRefreshControl
class is not implemented, so on devices running this OS (and any OS earlier than iOS 6) the operating system itself (well, rather its UIKit framework) doesn't contain the class and the symbol corresponding to it, so the application can't even start, even if it doesn't use the code suited for iOS6-only.
You also need to know that preprocessor macros are evaluated at compile time, and if your target is iOS 6, the code that you conditionally compile gets compiled and the system will try to execute that regardless of what version of iOS you're running the program on.
The solution: instead of using conditional compilation, use reflection and self-introspection to find out if the class is available at runtime:
Class UIRefreshControl_Class;
if ((UIRefreshControl_Class = objc_getClass("UIRefreshControl")) != Nil) {
// class available
id control = [[UIRefreshControl_class alloc] init];
// etc.
}
Upvotes: 1