Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading info.plist: inferred to have type AnyObject which may be unexpected

I inserted an integer in my info.plist file and, clearly, I'd like to retrieve it from my Swift UIViewController. The code is very simple:

class MyController: UIViewController {

    private let value: Int

    required init(coder aDecoder: NSCoder) {

        if let info = NSBundle.mainBundle().objectForInfoDictionaryKey("v"){
            value = info.integerValue
        }else{
            value = 0
        }

        super.init(coder: aDecoder)
    }

    //other auto-generated-methods
    //...

}

The function objectForInfoDictionaryKey returns an AnyObject? optional and I'm ok with this. But the compiler says to me that

Constant "info" inferred to have type AnyObject which may be unexpected

How can I solve this warning and why should I worry about the fact that the function returns an AnyObject? <-- this is a question mark... lol

Even if it returns an AnyObject I can downcast it if the object is not nil. I don't understand why the compiler complains about this.

like image 803
matteopuc Avatar asked Dec 14 '22 17:12

matteopuc


1 Answers

Xcode generally warns about variables which are inferred as AnyObject or AnyObject?. You can add a type annotation (as Xcode suggests) to silence the warning:

if let info : AnyObject = ...

I can only speculate why Xcode behaves like this, but one reason could be that you are "forced" to be aware that info might be of any object type and not perhaps the one that you expect.

So even if info.integerValue compiles, it may crash at runtime if the object is not of the expected type. In your case, if the dictionary value is not a NSNumber or NSString then info.integerValue with throw an exception.

The safe way is to do an optional cast:

if let info = NSBundle.mainBundle().objectForInfoDictionaryKey("v") as? NSNumber {
    value = info.integerValue
} else {
    value = 0
}

Do to the automatic re-mapping between NSNumber and Int you can write that also as

if let info = NSBundle.mainBundle().objectForInfoDictionaryKey("v") as? Int {
    value = info
} else {
    value = 0
}

Or as a one-liner using the nil-coalescing operator ??:

let value = NSBundle.mainBundle().objectForInfoDictionaryKey("v") as? Int ?? 0
like image 155
Martin R Avatar answered Feb 15 '23 22:02

Martin R