Reputation: 1262
I don't understand why this piece of Objective-C code:
id object = nil;
NSEnumerator *enumerator = ...;
while ((object = [enumerator nextObject])) {...}
can't be translated in Swift like this:
var key:AnyObject!
let enumerator:NSEnumerator = myNSDictionary.keyEnumerator()
while ( (object = enumerator.nextObject()) ) {...}
I have this error :
Type '()' does not conform to protocol 'BooleanType'
Upvotes: 2
Views: 6254
Reputation: 539705
In Objective-C, [enumerator nextObject]
returns an object pointer
which is nil
when when all objects have been enumerated,
and the value of an assignment
object = [enumerator nextObject]
is equal to the assigned value. In
while ((object = [enumerator nextObject])) { ... }
the while-block is executed as long as the expression compares
unequal to 0, where 0 in this case is the null pointer constant which is usually written as NULL
, or nil
for Objective-C pointers. So that
loop is equivalent to
while ((object = [enumerator nextObject]) != nil) { ... }
In Swift, an assignment does not have a value (it is a Void
),
therefore
while ( (object = enumerator.nextObject()) )
does not compile. You can forcibly cast it to a BooleanType
to make it compile but that will crash at runtime.
enumerator.nextObject()
returns AnyObject?
, i.e. an
optional object, which is nil
when all objects have been enumerated. The proper way to test the return value for nil
is
optional binding:
let enumerator = myNSDictionary.keyEnumerator()
while let key = enumerator.nextObject() {
print(key)
}
(Of course, bridging the NSDictionary
to a Swift Dictionary
and then using the Swift enumeration methods, as suggested in the
other answer, is a sensible alternative.)
Upvotes: 6
Reputation: 22926
You should enumerate over a dictionary as follows (which is described here in further detail):
Test dictionary declaration:
var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
Enumerate both key and value:
for (airportCode, airportName) in airports {
print("\(airportCode): \(airportName)")
}
// YYZ: Toronto Pearson
// LHR: London Heathrow
Enumerate just keys:
for airportCode in airports.keys {
print("Airport code: \(airportCode)")
}
// Airport code: YYZ
// Airport code: LHR
Enumerate just values:
for airportName in airports.values {
print("Airport name: \(airportName)")
}
// Airport name: Toronto Pearson
// Airport name: London Heathrow
Maybe there was a deeper reason you are choosing to use NSEnumerator
, but if not the above is alot more elegant from a Swift point of view.
Upvotes: 9