Objective-C @available guard AND'ed with more conditions

objective-c api_available
objective-c check ios version
@available(ios 11.0 *) objective c
how to use available objective-c
objective c mark method available
objective c available property
guard ios version
nsfoundationversionnumber

Objective-C has an @available expression in XCode 9+ / LLVM 5+ that allows you to guard a block of code to at least a certain OS version so that it won't emit unguarded availability warnings if you use APIs that are only available on that OS version.

The problem is that this availability guarding is that it only works if it's the sole expression in the condition of an if. If you use it in any other context, you get a warning:

@available does not guard availability here; use if (@available) instead

So for example, it doesn't work if you try to AND the availability check with other conditions in the if:

if (@available(iOS 11.0, *) && some_condition) {
  // code to run when on iOS 11+ and some_condition is true
} else {
  // code to run when on older iOS or some_condition is false
}

Any code that uses iOS 11 APIs inside the if block or in some_condition still will generate unguarded availability warnings, even though it is guaranteed that those pieces of code can only be reached when on iOS 11+.

I could turn it into two nested ifs, but then the else code would have to be duplicated, which is bad (especially if it's lots of code):

if (@available(iOS 11.0, *)) {
  if (some_condition) {
    // code to run when on iOS 11+ and some_condition is true
  } else {
    // code to run when on older iOS or some_condition is false
  }
} else {
  // code to run when on older iOS or some_condition is false
}

I can avoid duplication by refactoring the else block code into an anonymous function, but that requires defining the else block before the if, which makes the code flow hard to follow:

void (^elseBlock)(void) = ^{
  // code to run when on older iOS or some_condition is false
};

if (@available(iOS 11.0, *)) {
  if (some_condition) {
    // code to run when on iOS 11+ and some_condition is true
  } else {
    elseBlock();
  }
} else {
  elseBlock();
}

Can anyone come up with a better solution?


You do what you always do when you have complex conditional code in the middle of a function that makes the flow complex: you hoist it into another function.

- (void)handleThing {
    if (@available(iOS 11.0, *)) {
        if (some_condition) {
            // code to run when on iOS 11+ and some_condition is true
            return;
        }
    }

  // code to run when on older iOS or some_condition is false
}

Or you hoist the check into generic code (see Josh Caswell's; it's better than how I originally wrote this).

iOS, so, you can directly use that in if statements to check the availability You may also find Objective-C @available guard AND'ed with more� Objective-C has an @available expression in XCode 9+ / LLVM 5+ that allows you to guard a block of code to at least a certain OS version so that it won't emit unguarded availability warnings if you use APIs that are only available on that OS version.


#define SUPPRESS_AVAILABILITY_BEGIN \
    _Pragma("clang diagnostic push") \
    _Pragma("clang diagnostic ignored \"-Wunsupported-availability-guard\"")\
    _Pragma("clang diagnostic ignored \"-Wunguarded-availability-new\"")

#define SUPPRESS_AVAILABILITY_END \
    _Pragma("clang diagnostic pop")

#define AVAILABLE_GUARD(platform, os, future, conditions, codeIfAvailable, codeIfUnavailable) \
    SUPPRESS_AVAILABILITY_BEGIN \
    if (__builtin_available(platform os, future) && conditions) {\
        SUPPRESS_AVAILABILITY_END \
        if (@available(platform os, future)) { \
            codeIfAvailable \
        } \
    } \
    else { \
        SUPPRESS_AVAILABILITY_END \
        codeIfUnavailable \
    }

Usage:

AVAILABLE_GUARD(iOS, 11.0, *, true, {
    printf("IS AVAILABLE");
},
{
    printf("NOT AVAILABLE");
});

It works by using @available as a condition with additional optional conditions. Since you lose the ability to "guard", I suppressed the unguarded warnings but I also added an extra guard there to guard the rest of the code.. This makes it so you essentially lost nothing..

You get the guarding, you get the warnings gone and you get the extra conditions..

Marking API Availability in Objective-C, Similarly, you use the availability condition #available to execute code conditionally based on required platform and version conditions. Both kinds of availability� Objective-C has an @available expression in XCode 9+ / LLVM 5+ that allows you to guard a block of code to at least a certain OS version so that it won't emit unguarded availability warnings if you use APIs that are only available on that OS version.


How about wrapping the AND up in a function?

typedef BOOL (^Predicate)();

BOOL elevenAvailableAnd(Predicate predicate)
{
    if (@available(iOS 11.0, *)) {
        return predicate();
    }
    return NO;
}

Then you only have one branch:

if (elevenAvailableAnd(^{ return someCondition })) {
    // code to run when on iOS 11+ and some_condition is true
}
else {
    // code to run when on older iOS or some_condition is false
}

Or you could do without the Block if you prefer:

BOOL elevenAvailableAnd(BOOL condition)
{
    if (@available(iOS 11.0, *)) {
        return condition;
    }
    return NO;
}

Objective-C @available guard AND'ed with more conditions, Objective-C has an @available expression in XCode 9+ / LLVM 5+ that allows you to guard a block of code to at least a certain OS version so that it won't emit� In Swift, you can predicate if, guard, and while statements with an availability condition, #available, to determine the availability of APIs at runtime. Unlike the @available attribute, an #available condition can’t be used for Swift language version checks.


inline bool iOS13()
{
    if(@available(iOS 13, *))
        return true;
    else
        return false;
}

if(iOS13() && x == y)
    //...

Objective-C #available guard AND'ed with more conditions, Objective-C has an #available expression in XCode 9+ / LLVM 5+ that allows you to guard a block of code to at least a certain OS version so that it won't emit� Objective-C @available guard AND'ed with more conditions gpus_ReturnGuiltyForHardwareRestart Crash in _UIButtonBarStackView: breaking constraint when becomeFirstResponder sent


You could also simply use a flag:

BOOL doit = FALSE;

if (@available(iOS 11.0, *)) {
  if (some_condition) {
    doit = TRUE;
  }
}

if (doit) {
  // code to run when on iOS 11+ and some_condition is true
} else {
  // code to run when on older iOS or some_condition is false
}

Swift API Availability, if | guard | while #available( platform version , platform version , *) … #available expressions in Swift have the same syntax as their Objective-C� Objective-C // Initialize a Facebook credential with Firebase. FacebookAuthCredential *credential = [FIRFacebookAuthProvider credentialWithAccessToken:accessToken]; // Assuming the current user is an Apple user linking a Facebook provider.


Use the guard concept in Objective-C | by Tien-Che Tsai, `guard` syntax provides higher readability than writing with `if` statement. But how if I want to use this syntax in Objective-C? You could create a� if #available(iOS 9.0, *) { // use the feature only available in iOS 9 // for ex. UIStackView } else { // or use some work around } BUT it is not recommended to check the OS version. It is better to check if the feature you want to use is available on the device than comparing version numbers.


How to check an API is available in Swift for iOS and macOS., Availability checking in Swift gives us the ability to ask whether the user is running a specific or newer version of an operating system, and run� In Swift, you can predicate if, guard, and while statements with an availability condition, #available, to determine the availability of APIs at runtime. Unlike the @available attribute, an #available condition can't be used for Swift language version checks. The syntax of an #available expression resembles that of an @available attribute:


Checking API Availability in Swift, The iOS SDK is an ever-changing beast and checking API availability is a common problem. In Swift 2.0 Checking for API Availability in Objective-C. Check for� Objective-C: [AppsFlyerTracker sharedTracker].currencyCode = @"ZZZ";, Swift: AppsFlyerTracker.shared().currencyCode = "ZZZ" To learn about currency settings, display, and currency conversion, see our guide on revenue currency. The revenue value should not contain comma separators, currency sign, or text.