7

This question is geared for iOS version compatibility.

I know how to check if a function exists if it is a typical Objective-C style method using respondsToSelector. i.e. For a method such as:

- (void) someMethod:(NSInteger)someParameter;

You can use:

if ([self respondsToSelector:@selector(someMethod:someParameter)]) {
    //do something
}

But what about C-style functions? How can I check if a function exists that looks like:

void CStyleFunctionName(FoundationTypeRef parameter);

Thanks!

Keller
  • 17,051
  • 8
  • 55
  • 72
  • 1
    That's not a method, it's a function. Possible duplicate of [How to Check if the function exists in C/C++](http://stackoverflow.com/questions/8814705/how-to-check-if-the-function-exists-in-c-c) See also: [Can I redefine a function or check if it exists?](http://stackoverflow.com/questions/6916772/can-i-re-define-a-function-or-check-if-it-exists) – jscs Sep 20 '12 at 17:32
  • 1
    You can do `if (CStyleMethodName != NULL) { ... }` to see if the symbol is defined. That's what you want to do if you want to be compatible with older versions of iOS for example. – Fabian Kreiser Sep 20 '12 at 17:34
  • 1
    @FabianKreiser that only works if weak linking is supported. –  Sep 20 '12 at 17:35
  • I know, but it works in the latest versions of Xcode and @Keller asked more questions about iOS 6 recently and I think he's currently updating an app and wants to make it backwards compatible. ;) – Fabian Kreiser Sep 20 '12 at 17:40
  • My question was geared toward iOS so Fabian's solution is the most elegant for that. Also, my endless chagrin for calling it a "method" instead of a "function" :) I've been in iOS land for too long! – Keller Sep 20 '12 at 17:40
  • @FabianKreiser submit you solution as an answer and I will accept it. – Keller Sep 20 '12 at 17:43
  • @Keller so why is my solution not good enough? Do you really believe it doesn't work on iOS? –  Sep 20 '12 at 17:45
  • 1
    So, you didn't read [the docs](https://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/cross_development/Using/using.html), did you? – netcoder Sep 20 '12 at 18:16

2 Answers2

11

Xcode (at least since 4.3) supports weak linking and you can do the following to see if you can call a C function:

// UIGraphicsBeginImageContextWithOptions() was introduced in iOS 4 in order to support the Retina displays.
if (UIGraphicsBeginImageContextWithOptions != NULL) {
    UIGraphicsBeginImageContextWithOptions(...);
}
else {
    UIGraphicsBeginImageContext();
}
Fabian Kreiser
  • 8,307
  • 1
  • 34
  • 60
  • any idea why do I still get an error on this line? if (ABAddressBookRequestAccessWithCompletion != NULL) Use of undeclared identifier 'ABAddressBookRequestAccessWithCompletion' – schystz Dec 18 '12 at 08:41
  • Yeah, the framework is properly linked and I even tried making it weak (optional) lib but to no avail... I was compiling for iOS5 SDK by the way. Never had problem with iOS6 – schystz Dec 18 '12 at 11:06
  • But did you import the header? `#import ` – Fabian Kreiser Dec 18 '12 at 13:24
  • I found out it was caused by the additional framework path that was added on the Build Settings. I am using both iOS5 and iOS6 SDKs in xcode and the I think compiler looks on the iOS5 instead that's why I'm having a problem. (I'm not really sure though...) It works fine now! – schystz Dec 19 '12 at 07:46
  • Where did you see this in the Build Settings, @schystz? I think I may be having the same problem. Thanks! – JRoss Jan 13 '13 at 18:31
  • You can search for "Framework Search Paths" and remove anything you don't need. (Mine is empty bdw) – schystz Jan 16 '13 at 14:07
7

Dynamic loading:

#include <dlfcn.h>

void *fptr = dlsym(NULL, "CStyleFunctionName");
if (fptr != NULL) {
    // existent
} else {
    // nonexistent
}

Also note that in C, there are no methods, only functions.

  • This is great too. But as my question was geared towards iOS, Fabian's solution is more appropriate. Thank you. – Keller Sep 20 '12 at 17:43
  • @Keller why is Fabian's solution more appropriate? Why my answer isn't good for iOS? –  Sep 20 '12 at 17:44
  • It does work. To clarify, Fabian's solution is just slightly cleaner and doesn't require a #include. – Keller Sep 20 '12 at 17:47
  • @Keller except that 1. it requires weak linking to be supported, 2. it does need an include: `NULL` is defined in ``. –  Sep 20 '12 at 17:48
  • 2
    Wow, why are you angry? My answer is just simpler and is recommended in Apple's documentation. It might not be as general as yours, but it's the appropriate way of doing it in this case. Why would you want to call `dlsym()` if the compiler can do that work for you? – Fabian Kreiser Sep 20 '12 at 18:08