Aaron Hayman
Aaron Hayman

Reputation: 8502

Swift convert bool to NSRange

This does not work (of course) nothing prints and Xcode spits out an warning about Cast always failing:

let bool = true  
if let range = bool as? NSRange {
  print(range)
}

Why does this work? I would think it should not:

let bool: AnyObject = true    
if let range = bool as? NSRange {
  print(range)
}

This will actually print out (0,0) ... which might kind of make sense if it were false, but it's true so, yeah... doesn't make sense to me.

Same behavior in Swift 1.2 or 2.0. But it's kind of making me doubt Swift's type system a little.

Upvotes: 1

Views: 109

Answers (1)

jtbandes
jtbandes

Reputation: 118681

This isn't so much a fault of Swift's type system as it is a side effect of the Objective-C interoperability.

let bool: AnyObject = true is effectively let bool = NSNumber(bool: true). This is no longer a Swift Bool, but it's an Obj-C (Foundation) NSNumber object.

Then, let range = bool as? NSRange tries to convert your value to NSRange. NSNumber is a subclass of NSValue, so this is similar to

let range = NSNumber(bool: true).rangeValue

which returns {0,0}. That's how NSValue works. Here's some disassembly from Hopper:

disassembly

This might be fixable from the Swift team's perspective, if they're more careful about checking the type before doing the conversion. You should consider filing a bug.

Upvotes: 1

Related Questions