enumerateObjectsUsingBlock in Swift
Foundation
enumerateObjectsUsingBlock:
is not a method on Array but on NSArray. If you want to use it you'll need an instance of NSArray rather than Array.
import Foundation
var array: NSArray = ["Some", "strings", "in", "an", "array"]
array.enumerateObjectsUsingBlock({ object, index, stop in
//your code
})
if you have an existing array, you can cast a swift Array
to an NSArray
using as
var cocoaArray = swiftArray as NSArray
or if you simply import Foundation
the Swift compiler will automatically bridge your Swift array to an NSArray and all the NSArray methods will become available for you.
Swift 1
or you can just use Swift's enumerate
function:
for (index, value) in enumerate(array) {
// your code
}
Swift 2
In Swift 2, enumerate
is no longer a free function, now it's in a protocol extension!
for (index, value) in array.enumerate() {
// your code
}
Swift 3
And in Swift 3, enumerate
was renamed to enumerated
for (index, value) in array.enumerated() {
// your code
}
enumerateObjectsUsingBlock - casting parameters in Swift
In Swift you cannot "tweak" the block/closure signature as in
Objective-C, you have to cast explicitly. Either with an
optional cast:
array.enumerateObjectsUsingBlock({ object, index, stop in
if let str = object as? String {
println(str)
}
})
or with a forced cast if you are sure that all objects are strings:
array.enumerateObjectsUsingBlock({ object, index, stop in
let str = object as String // `as!` in Swift 1.2
println(str)
})
Since NSArray
bridges to Array
seamlessly, you can alternatively
use the Array
enumeration:
for str in array as [String] {
println(str)
}
or, if you need the elements together with their index:
for (index, str) in enumerate(array as [String]) {
println("\(index): \(str)")
}
Update for Swift 3.0
With enumerateObjects(using:)
:
array.enumerateObjects(using: { (object, index, stop) in
if let str = object as? String {
print("\(index): \(str)")
}
})
Enumerate as Swift array:
if let a = array as? [String] {
for str in a {
print(str)
}
}
Enumerate elements and indices as Swift array:
if let a = array as? [String] {
for (index, str) in a.enumerated() {
print("\(index): \(str)")
}
}
How do I use enumerateObjectsUsingBlock in Swift
You’ve left a bit of Objective-C in your Swift (some rogue square brackets):
if(![self.destinationIdentifier == key]) {
However, you would probably find it easier to use Swift’s for-in than array.enumerateObjectsUsingBlock
:
override func didReceiveMemoryWarning() {
for key in self.viewControllersByIdentifier.allKeys {
// note key will be an AnyObject so you need to cast it to an appropriate type…
// also, this means you can use != rather than ! and ==
if self.destinationIdentifier != key as? NSString {
self.viewControllersByIdentifier.removeObjectForKey(key)
}
}
super.didReceiveMemoryWarning()
}
How to stop enumerateObjectsUsingBlock Swift
In Swift 1:
stop.withUnsafePointer { p in p.memory = true }
In Swift 2:
stop.memory = true
In Swift 3 - 4:
stop.pointee = true
Swift 2.2 enumerateObjectsUsingBlock - stop
Your syntax is pretty weird ;-)
This works in both Swift 2.1 and 2.2
let array: NSArray = [1, 2, 3, 4, 5]
array.enumerateObjectsUsingBlock { (object, idx, stop) in
print(idx)
if idx == 3 {
stop.memory = true
}
}
Swift 3:
let array: NSArray = [1, 2, 3, 4, 5]
array.enumerateObjects({ (object, idx, stop) in
print(idx)
if idx == 3 {
stop.pointee = true
}
})
Nevertheless – as suggested in the other answer – use native Swift Array
.
Transform enumerateObjectsUsingBlock to Fast Enemuration - Swift
As long as newVisibleItems is declared as [AnyObject]
, your code won't compile due to Swift's strict type checking.
To ensure newVisibleItems
is an array of expected types, you have to wrap your for
loop inside a downcast:
if let newVisibleItems = newVisibleItems as? [UIDynamicItem] {
for (index, attribute) in enumerate(newVisibleItems) {
...
}
}
If the reason of this error lays inside UIKit, be assured that Apple is working hard right now to ensure that every single declaration in the "swiftified" version of their frameworks returns a proper type, instead of a combination of AnyObject!
s.
When to use enumerateObjectsUsingBlock vs. for
Ultimately, use whichever pattern you want to use and comes more naturally in the context.
While for(... in ...)
is quite convenient and syntactically brief, enumerateObjectsUsingBlock:
has a number of features that may or may not prove interesting:
enumerateObjectsUsingBlock:
will be as fast or faster than fast enumeration (for(... in ...)
uses theNSFastEnumeration
support to implement enumeration). Fast enumeration requires translation from an internal representation to the representation for fast enumeration. There is overhead therein. Block-based enumeration allows the collection class to enumerate contents as quickly as the fastest traversal of the native storage format. Likely irrelevant for arrays, but it can be a huge difference for dictionaries."Don't use enumerateObjectsUsingBlock when you need to modify local variables" - not true; you can declare your locals as
__block
and they'll be writable in the block.enumerateObjectsWithOptions:usingBlock:
supports either concurrent or reverse enumeration.with dictionaries, block based enumeration is the only way to retrieve the key and value simultaneously.
Personally, I use enumerateObjectsUsingBlock:
more often than for (... in ...)
, but - again - personal choice.
Compiler error when using `enumerateObjectsUsingBlock` of PHFetchResult
I finally found the answer to my question. a first parameter of a block of enumerateObjectsUsingBlock
is AnyType!
. Therefore, obj
argument for append
method should be downcast with as!
.
Anyway, I think an error message is not exact to point out this mistake. It seems that the compiler give this kind of an error message to a programmer when something wrong is in a block.
Cannot convert value of type - Swift
Looks like you're using the incorrect type annotations in your completion closure. This should do:
stops.enumerateObjectsUsingBlock({(stopItem, _ , _) in
guard let stopItem = stopItem as? SBStop else { return }
stopLocation = CLLocation(latitude: stopItem.latitude, longitude: stopItem.longitude)
stopItem.distance = stopLocation.distanceFromLocation(location)
})
Explanation:
The library that you're using defines the parameters of the completion block as (AnyObject, Int, UnsafeMutablePointer)
. If you're expecting the AnyObject to be of a specific type, you'll need to cast it appropriately (in this case using guard let
)
The _
is a Swift-ism that indicates an unused parameter.
The -> Void
is implied for closures unless otherwise specified, so it's not explicitly needed here.
Related Topics
Convert String to Cgfloat in Swift
How to Convert Nsurl to String in Swift
Healthkit Error: Missing Com.Apple.Developer.Healthkit Entitlement
What's the Swift Equivalent of Objective-C's "#Ifdef _Iphone_11_0"
Swift Diffabledatasource Make Insert&Delete Instead of Reload
Swift 3 and Firebase: Retrieve Auto Id Value from Snapshot
Xcode 10 Beta 5 - Clang: Error: Linker Command Failed with Exit Code 1
Rxswift: Observable While a Button Holds Down
Arkit - How to Put 3D Object on Qrcode
Value for Swift_Version Cannot Be Empty
Swift How to Cast from Int? to String
Uisearchcontroller in Navigationitem iOS 11 Apple Way
Swift 4.2+ Seeding a Random Number Generator