Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if a function is available in Swift?

I would like to detect if the user has enabled Reduce Transparency. It's simple you just call the func UIAccessibilityIsReduceMotionEnabled() and it returns a Bool. But my app targets iOS 7 and 8 and this function isn't available on iOS 7.

In Objective-C, this is how I checked to see if that function exists:

if (UIAccessibilityIsReduceMotionEnabled != NULL) { }

In Swift, I can't figure out how to check if it exists or not. According to this answer, you can simply use optional chaining and if it's nil then it doesn't exist, but that is restricted to Obj-C protocols apparently. Xcode 6.1 doesn't like this:

let reduceMotionDetectionIsAvailable = UIAccessibilityIsReduceMotionEnabled?()

It wants you to remove the ?. And of course if you do so it will crash on iOS 7 because that function doesn't exist.

What is the proper way to check if these types of functions exist?

like image 523
Jordan H Avatar asked Nov 03 '14 02:11

Jordan H


People also ask

How to call a function in Swift?

To use a function, you “call” that function with its name and pass it input values (known as arguments) that match the types of the function's parameters. A function's arguments must always be provided in the same order as the function's parameter list.

How to check if an element is present in an array in Swift?

Swift Array contains() The contains() method checks whether the specified element is present in the array or not.

What is @available in Swift?

@available. In Swift, you use the @available attribute to annotate APIs with availability information, such as “this API is deprecated in macOS 10.15” or “this API requires Swift 5.1 or higher”.

What is variadic function in Swift?

In computer programming, a variadic function is a function which accepts a variable number of arguments. The function arguments are represented by … (three period characters) after the argument's type that can be accessed into their body as an array .


1 Answers

You could check to see if you're running in iOS 8 or higher --

var reduceMotionEnabled = false
if NSProcessInfo().isOperatingSystemAtLeastVersion(NSOperatingSystemVersion(majorVersion: 8, minorVersion: 0, patchVersion: 0)) {
    reduceMotionEnabled = UIAccessibilityIsReduceMotionEnabled()
}

I don't think there's another way to tell. So in theory, if you were able to check, trying to access the function name without the () would give you nil in iOS 7 and the () -> Bool function in iOS 8. However, in order for that to happen, UIAccessibilityIsReduceMotionEnabled would need to be defined as (() -> Bool)?, which it isn't. Testing it out yields a function instance in both versions of iOS that crashes if called in iOS 7:

let reduceMotionDetectionIsAvailable = UIAccessibilityIsReduceMotionEnabled
// reduceMotionDetectionIsAvailable is now a () -> Bool
reduceMotionDetectionIsAvailable()
// crashes in iOS7, fine in iOS8

The only way I can see to do it without testing the version is simply to define your own C function to check in your bridging header file, and call that:

// ObjC
static inline BOOL reduceMotionDetectionIsAvailable() {
    return (UIAccessibilityIsReduceMotionEnabled != NULL);
}

// Swift
var reduceMotionEnabled = false
if reduceMotionDetectionIsAvailable() {
    reduceMotionEnabled = UIAccessibilityIsReduceMotionEnabled()
}
like image 114
Nate Cook Avatar answered Nov 09 '22 10:11

Nate Cook