8

Is it possible to detect if some global function (not class method) is defined (in iOS)? Something like respondsToSelector in a class...

JMI
  • 2,530
  • 15
  • 26

2 Answers2

6

Swift currently does not support looking up global functions.

For C functions (most global functions from Apple's frameworks are C functions) there are at least two ways:

  • using a weakly linked symbol
  • the dynamic linker API: dlopen

Both check dynamically (at runtime) if a symbol can be found.

Here's an example that checks if UIGraphicsBeginImageContextWithOptions (introduced with iOS 4) is available:

void UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale) __attribute__((weak));

static inline BOOL hasUIGraphicsBeginImageContextWithOptions() {
    return UIGraphicsBeginImageContextWithOptions != NULL;
}

Here's the same check, using dlsym:

#import <dlfcn.h>

static inline BOOL hasUIGraphicsBeginImageContextWithOptions() {
    return dlsym(RTLD_SELF, "UIGraphicsBeginImageContextWithOptions") != NULL;
}

The advantage of using dlsym is that you don't need a declaration and that it's easily portable to Swift.

Nikolai Ruhe
  • 81,520
  • 17
  • 180
  • 200
  • Now I remember I actually have used the weak linking myself before. I am not really sure if that would work for Swift globals though. – Sulthan Jul 13 '16 at 14:42
  • @Sulthan It wouldn't, because Objective-C cannot see Swift globals. But perhaps that is not what the OP is asking. – matt Jul 13 '16 at 14:46
  • @Sulthan Swift's name mangling is preventing simple symbol lookup. – Nikolai Ruhe Jul 13 '16 at 15:23
0

No, it's not possible in Swift.

Even respondsToSelector uses the Obj-C runtime and can be used only for functions available in Obj-C.

Sulthan
  • 128,090
  • 22
  • 218
  • 270
  • How will you get past the compiler if the function does not exist? – Feldur Jul 13 '16 at 15:31
  • @Feldur That's why we have `#available`. – Sulthan Jul 13 '16 at 15:58
  • @Feldur You can always declare a function (as `extern`, but that's the default) and then leave it up to the dynamic linker to resolve the symbol. That's what happens all of the time when linking to system frameworks. – Nikolai Ruhe Jul 13 '16 at 15:59
  • 1
    Wa's the question not relative to doing this in Swift? Extern does not seem to be a swift keyword – Feldur Jul 13 '16 at 16:29