Skip to content

Instantly share code, notes, and snippets.

@aral
Last active August 29, 2015 14:17
Show Gist options
  • Select an option

  • Save aral/f65d30da4aff818af3c4 to your computer and use it in GitHub Desktop.

Select an option

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

aral commented Mar 19, 2015

Copy link
Copy Markdown
Author

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

@aral

aral commented Mar 19, 2015

Copy link
Copy Markdown
Author

(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
Copy Markdown

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

aral commented Mar 19, 2015

Copy link
Copy Markdown
Author

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

jaanus commented Mar 19, 2015

Copy link
Copy Markdown

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

aral commented Mar 20, 2015

Copy link
Copy Markdown
Author

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

@jaanus

jaanus commented Mar 20, 2015

Copy link
Copy Markdown

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

fabrice commented Mar 20, 2015

Copy link
Copy Markdown

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

jaanus commented Mar 20, 2015

Copy link
Copy Markdown

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