Is there a way to test for the existence of C functions in Objective-C? I'm looking for something like "respondsToSelector," but for C functions.
More specifically, I'm trying to test for the existence of "UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque>, CGFloat scale)" in iOS.
Thanks.
if(&UIGraphicsBeginImageContextWithOptions != NULL)
UIGraphicsBeginImageContextWithOptions();
else NSLog(#"No UIGraphicsBeginImageContextWithOptions function");
Yes, see the documentation on weak linking.
It'll work out to checking if the function pointer is NULL before calling the function.
Since UIGraphicsBeginImageContextWithOptions is only present in iOS 4.0 and later, you can check the iOS target version with the __IPHONE_OS_VERSION_MAX_ALLOWED macro:
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
UIGraphicsBeginImageContextWithOptions(...);
#else
// Function not available, fail gracefully
#endif
Related
Consider an app that needs to be compatible with iOS 5 and iOS 6.
Is there a way to mark the code that is there purely for iOS 5 compatibility, so that it appear as a compile error (or warning) when -eventually- the deployment target changes to iOS 6?
Something like this:
#IF_DEPLOYMENT_TARGET_BIGGER_THAN_IOS_5
#OUTPUT_ERROR_MESSAGE
#ENDIF
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return YES;
}
If not, what is the best alternative?
Try this:
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 60000
#warning This pre-6.0 code isn't needed anymore
#endif
- (BOOL)shouldAutorotateToInterfaceOrientation(UIInterfaceOrientation)toInterfaceOrientation {
return YES;
}
This code will cause a compiler warning once the Deployment Target is set to 6.0 or later.
#define MY_CONDITIONAL_DEPRECATED_ATTRIBUTE __deprecated
use it on all methods BUT until you need it turn it quiet
#define MY_CONDITIONAL_DEPRECATED_ATTRIBUTE
Consider looking at how Apple marks that sort of thing in their framework classes. It seems they're making use of the Availability.h and AvailabilityInternal.h classes in the SDK.
I m looking for a preprocessor or something like that that will help me to define variables or methods depending on the device type iPhone or iPad.
I found something related here : Preprocessor-IF doesn't work - where it is advised to use
#ifdef UI_USER_INTERFACE_IDIOM
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#else
#define IS_IPAD false
#endif
#define WIDTH (IS_IPAD ? 768 : 320)
#define HEIGHT (IS_IPAD ? 1024 : 480)
but suppose I have variables defined in the interface that are to be used separately based on device
Class1 *object1; //specific for iPhone
Class2 *object2; //specific for iPad
Or methods that are used depending on device, how do I differentiate?
You can use as many as objects in any class, the main thing is at which time you are allocating those classes, you will be writing the code, calling the methods, depending on the device.
So this doesn't make any sense, you can have both objects in the class, & declare in the header file. And in the dealloc check before calling release to those objects.
I am unable to get clear idea about the following method:
- (BOOL) isPad {
#ifdef UI_USER_INTERFACE_IDIOM
return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
#else
return NO;
#endif
}
Actually for iPad applications this method is used but I don't understand that this method actually does, so if anyone could explain it in detail it would be very helpful for me.
Thanks in advance.
The method simply checks if the UI_USER_INTERFACE_IDIOM macro has been defined.
If it is available, it checks to see whether the macro is equal to UIUserInterfaceIdiomPad. If the comparison is true, it returns YES, otherwise if will return NO.
If the macro has not been defined, it means you are running iOS < 3.2 so it is definitely not an iPad.
For documentation, see http://developer.apple.com/library/ios/documentation/uikit/reference/UIKitFunctionReference/Reference/reference.html#//apple_ref/c/macro/UI_USER_INTERFACE_IDIOM
As the name suggests, tells you whether the current device that your app is running on is an iPad or not. Returns YES for iPad 1 & 2, and NO for iPhones and iPods.
The #ifdef is the pre-compiler checking to see if a variable UI_USER_INTERFACE_IDIOM is defined and then if it is defined as UIUserInterfaceIdiomPad. If it is defined as UIUserInterfaceIdiomPad that means it is being compiled for the iPad and returns YES, otherwise it returns NO.
I read from the header file (UIApplication.h):
typedef NSUInteger UIBackgroundTaskIdentifier;
UIKIT_EXTERN const UIBackgroundTaskIdentifier UIBackgroundTaskInvalid __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_4_0);
It seems that UIBackgroundTaskInvalid is just an ordinary NSUInteger with a given value. Now that I'm writing code that has to be compatible with jailbreaking iOS 3.1.3 (where UIBackgroundTaskInvalid is not defined yet). I might need the real value behind it. Anyone can help?
Thanks in advance.
Di
You can check it with
#if !defined UIBackgroundTaskIdentifier
// Pre iOS 4 Fallback
#endif
The sample above only checks the value on compile time. If you need these kind of checks on run-time you can check this great article.
As my iPhone app can run on both OS 3 and 4, I need a way to safely test for iOS 4 SDK features.
I like to avoid checking the [UIDevice ... systemVersion] string (I wonder why Apple failed to provide a numeric value here for easy testing, as it's available on OS X).
Anyway. The usual clean way to test for SDK features is to check if a class reponds to a selector, like this:
if ([UIApplication instancesRespondToSelector:...
And for C methods, one simply checks if the function pointer is NULL:
if (newFunction != NULL) ...
But my problem is that I need to check if a global variable exists. E.g. this one:
extern NSString *const UIApplicationDidEnterBackgroundNotification __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_4_0);
Any idea how one can test their existence at runtime?
Extracted from the help document "SDK Compatibility guide":
Check the availability of an external (extern) constant or a notification name by explicitly comparing its address—and not the symbol’s bare name—to NULL or nil.
For instance, if you wanted to check for the key UIKeyboardFrameBeginUserInfoKey in a keyboard notification dictionary, which is only available in 3.2 and later, you could write:
if (&UIKeyboardFrameBeginUserInfoKey) {
blah;
} else {
blah;
}
the default method is
UIDevice* device = [UIDevice currentDevice];
BOOL backgroundSupported = NO;
if ([device respondsToSelector:#selector(isMultitaskingSupported)])
backgroundSupported = device.multitaskingSupported;
When the test is passed your "it exists in 4.x" global variable shoudl be available.
By the way - it answers if OS4 is there an if the device supports multitasking.
Manfred