Skip to content

Instantly share code, notes, and snippets.

@aral
Last active August 29, 2015 14:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aral/f65d30da4aff818af3c4 to your computer and use it in GitHub Desktop.
Save aral/f65d30da4aff818af3c4 to your computer and use it in GitHub Desktop.
AnyObject? to unwrapped value
let a = NSDictionary(object: NSNumber(bool: true), forKey: "boolKey")
let b: AnyObject? = a.objectForKey("boolKey")
if let b:AnyObject = b, c:NSNumber = (b as? NSNumber) where c.boolValue == true
{
println("It’s true.")
}
@aral
Copy link
Author

aral commented Mar 19, 2015

Any ideas for a shorter method with better intent for doing this?

@aral
Copy link
Author

aral commented Mar 19, 2015

(Thanks to Joe Groff, via Twitter) “You should be able to do 'a as? NSNumber' in one step without unwrapping 'a'; it'll produce nil if 'a' is nil or not NSNumber.”

//…
if let c:NSNumber = (b as? NSNumber) where c.boolValue == true
{
    println("It’s true.")
}

@paulofierro
Copy link

Doesn't really answer the question, but IMO its a bit easier to read.

let a: NSDictionary = ["boolKey" : true]
let b: AnyObject? = a["boolKey"]

if let c:NSNumber = (b as? NSNumber) where c.boolValue == true
{
    println("It's true.")
}

@aral
Copy link
Author

aral commented Mar 19, 2015

And that’s actually not that bad in terms of intent/verbosity. Actual code (from KVO handler):

override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>)
{
  // … (keyPath == "loading")
  if let isLoading:NSNumber = change["new"] as? NSNumber where isLoading.boolValue == false
  {
    //…
}

@jaanus
Copy link

jaanus commented Mar 19, 2015

whats all the NSNumber business?

let a = NSDictionary(object: NSNumber(bool: true), forKey: "boolKey")
if let b = a.objectForKey("boolKey") as? Bool where b == true {
    println("bool value: \(b)")
}

@aral
Copy link
Author

aral commented Mar 20, 2015

Hey Jaanus, I hadn’t realised you could go directly to a Swift type like that. Thanks, that’s way better :)

@jaanus
Copy link

jaanus commented Mar 20, 2015

That’s one of the profound things of Swift for me. There is no distinction between “primitive/C” and “object” types, they behave much more similarly.

@fabrice
Copy link

fabrice commented Mar 20, 2015

a.objectForKey("boolKey") as? Bool will always return a Bool if it's a NSNumber, even if that NSNumber is actually a double. You may want to ensure it is really a bool with:

let number = a.objectForKey("boolKey") as! NSNumber
if number.objCType == NSNumber( bool: true ).objCType {
  // number is a Bool
}

It kinda sucks, but it's the only way to know for sure in Swift. In ObjC you can compare the pointers with the singletons @yES / @no.

@jaanus
Copy link

jaanus commented Mar 20, 2015

The usual semantics of casting other types to bools are that 0 is NO/false and anything else is YES/true. This seems to be working correctly with casting directly to Bool even if the NSNumber originally contained a float.

If it’s important to find out more granularly what NSNumber contained originally and what type it was, then of course this shorthand is not sufficient and @fabrice’s solution should be used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment