'Negate #available statement

I want to execute a code block only on devices running with an OS older than iOS8. I can't do:

if #available(iOS 8.0, *) == false {
    doFoo() 
}

The solution I'm using for now is:

if #available(iOS 8.0, *) { } else { 
    doFoo() 
}

, but it feels clunky. Is there another way to negate the #available statement elegantly with Swift ?



Solution 1:[1]

In Swift 5.6, you can now do the following:

if #unavailable(iOS 15) {
    // Under iOS 15
} else {
    // iOS 15+
}

Or just the following depending on your case:

if #unavailable(iOS 15) {
    // Under iOS 15
}

This is part of SE-0290: Negative availability.

Solution 2:[2]

I use a guard for this:

guard #available(iOS 8.0, *) else {
    // Code for earlier OS
}

There's slight potential for awkwardness since guard is required to exit the scope, of course. But that's easy to sidestep by putting the whole thing into its own function or method:

func makeABox()
{
    let boxSize = .large

    self.fixupOnPreOS8()

    self.drawBox(sized: boxSize)
}

func fixupOnPreOS8()
{
    guard #available(iOS 8, *) else {
        // Fix up
        return
    }
}

which is really easy to remove when you drop support for the earlier system.

Solution 3:[3]

It is not possible to have logic around the #available statement.

Indeed, the statement is used by the compiler to infer what methods can be called within the scope it embraces, hence nothing can be done at runtime that would conditionally execute the block.

It is possible though to combine conditions, using a comma, as follows

if #available(iOS 8.0, *), myNumber == 2 {
  // some code
}

Solution 4:[4]

Seems it's the best solution, before Swift2 you had to use other methods such as using ready-to-use classes wrote by individuals. But that's fine, you can set a variable in viewDidLoad() and use it to detect the older devices:

var isNewerThan8: Bool = false

func viewDidLoad(){
   if #available(iOS 8.0, *) { 
      isNewerThan8 = true
   } else { 
      isNewerThan8 = false
   }
}

func myFunction(){
   if isNewerThan8 {
     //foo
   }else{
    //boo
   }
}

Solution 5:[5]

Swift 5.6, Xcode 13.3 Beta

if #unavailable(iOS 13, *) {
   // below iOS 13
} else {
  // iOS 13 and above
}

Swift 5.5 and earlier

a simple way to check is by using #available with a guard statement

guard #available(iOS 13, *) else {
   // code for earlier versions than iOS 13
   return
} 

another way is to use if/else

if #available(iOS 13, *) {} else {
    // code for earlier versions than iOS 13
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 jscs
Solution 3 tomahh
Solution 4 Maysam
Solution 5