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

前端 未结 8 1264
眼角桃花
眼角桃花 2021-01-01 11:17

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 ava

相关标签:
8条回答
  • 2021-01-01 11:34

    Defined

    #define AT_AVAILABLE(...) \
    _Pragma("clang diagnostic push") \
    _Pragma("clang diagnostic ignored \"-Wunsupported-availability-guard\"") \
    _Pragma("clang diagnostic ignored \"-Wunguarded-availability-new\"") \
    __builtin_available(__VA_ARGS__) \
    _Pragma("clang diagnostic pop")
    

    Usage:

    if (AT_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
    }
    

    or

    import this in PCH file

    #pragma clang diagnostic ignored "-Wunsupported-availability-guard"
    #pragma clang diagnostic ignored "-Wunguarded-availability-new"
    

    Usage:

    if (AT_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
    }
    
    
    0 讨论(0)
  • 2021-01-01 11:41

    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;
    }
    
    0 讨论(0)
  • 2021-01-01 11:42
    inline bool iOS13()
    {
        if(@available(iOS 13, *))
            return true;
        else
            return false;
    }
    
    if(iOS13() && x == y)
        //...
    
    0 讨论(0)
  • 2021-01-01 11:42

    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
    }
    
    0 讨论(0)
  • 2021-01-01 11:43

    The way I came up with that seems to change the layout of the code the least is:

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

    which is still ugly.

    0 讨论(0)
  • 2021-01-01 11:45

    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).

    0 讨论(0)
提交回复
热议问题