Beau Nouvelle
Beau Nouvelle

Reputation: 7252

How to do an availability check on class variables

My current project supports iOS 7+ and in one of my view controllers I'm trying to use both UIAlertView and UIAlertController.

I have the #available conditional working in my methods, but I'm not sure how to wrap the vars.

When I have:

var alertController: UIAlertController!
var alertView: UIAlertView!

I get an error message telling me UIAlertController is only available in iOS 8+ and the option to 'Fix It' by "Adding @available to enclosing class". However I think this marks the entire class, and that's not what I want.

Upvotes: 8

Views: 5888

Answers (2)

Daniel Galasko
Daniel Galasko

Reputation: 24247

I just came across this issue and I too have struggled to find a solution so ended up making the variable lazy and defaulting to nil whilst adding availability annotations

For your implementation that would look as follows:

@available(iOS 8.0, *)
lazy var alertController: UIAlertController? = { return nil }()

Then whenever you try and access that property the compiler will make sure its guarded in an availability check so that you always have:

if #available(iOS 8.0, *) {
    self.alertController = ...
} else 
    self.alertView = ...
}

Upvotes: 25

Oliver Zhang
Oliver Zhang

Reputation: 529

If you just need to use alert in one function, you can just move your code into the func block and XCode 7 will come up with suggestion that works.

What if you need to use alert in several func blocks and refer to the same alert object over and over?

You can use a new UIResponder and downcast it to either UIAlertController or UIView based on availability. I haven't test it in my project, but it should work.

let alertContainer: UIResponder?

init () {
    if #available(iOS 8.0, *) {
        let alertController: UIAlertController!
        alertContainer = alertController
    } else {
        let alertView: UIAlertView!
        alertContainer = alertView
    }
}

func someFunction () {
    if #available(iOS 8.0, *) {
        var alertController = alertContainer as! UIAlertController
        // use the alertController
    } else {
        var alertView = alertContainer as! UIAlertView
        // use the UIAlertView
    }
}

This actually adds more codes, but it passes Xcode's check. If you come up with a better solution, please let me know.

Upvotes: 2

Related Questions