Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Negate #available statement

Tags:

ios

swift

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 ?

like image 489
tomahh Avatar asked Sep 17 '15 15:09

tomahh


People also ask

What does this negate mean?

Definition of negate transitive verb. 1 : to deny the existence or truth of negated and denied her own honest reactions— Sara H. Hay. 2 : to cause to be ineffective or invalid Alcohol can negate the effects of some medicines.

What is an example of negate?

Negate is defined as to deny, to prove false or to cause something to not be needed. An example of to negate is to conduct a study to prove a theory false. An example of to negate is for an umbrella to take away the need for a hood. (computers) To perform the machine logic operation NOT gate.

Does negate mean deny?

verb (used with object), ne·gat·ed, ne·gat·ing. to deny the existence, evidence, or truth of: an investigation tending to negate any supernatural influences. to nullify or cause to be ineffective: Progress on the study has been negated by the lack of funds.

What is the synonym of negate?

Some common synonyms of negate are abrogate, annul, invalidate, and nullify. While all these words mean "to deprive of effective or continued existence," negate implies the destruction or canceling out of each of two things by the other. the arguments negate each other.


4 Answers

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.

like image 68
jscs Avatar answered Oct 07 '22 01:10

jscs


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.

like image 41
George Avatar answered Oct 07 '22 03:10

George


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
}
like image 9
tomahh Avatar answered Oct 07 '22 03:10

tomahh


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
   }
}
like image 3
Maysam Avatar answered Oct 07 '22 01:10

Maysam