Enumerateobjectsusingblock in Swift

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 the NSFastEnumeration 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



Leave a reply



Submit