36

How do I stop a block enumeration?

    myArray.enumerateObjectsUsingBlock( { object, index, stop in
        //how do I stop the enumeration in here??
    })

I know in obj-c you do this:

    [myArray enumerateObjectsUsingBlock:^(id *myObject, NSUInteger idx, BOOL *stop) {
        *stop = YES;
    }];
random
  • 8,568
  • 12
  • 50
  • 85
  • possible duplicate of [enumerateObjectsUsingBlock in Swift](http://stackoverflow.com/questions/24120115/enumerateobjectsusingblock-in-swift) – David Berry Jun 13 '14 at 21:51
  • The link basically says, don't use enumerateObjectsUsingBlock in swift, because the functionality is better expressed using `for ... in.. enumerate` – David Berry Jun 13 '14 at 21:52
  • 4
    @David: not a duplicate. the other thread does not cover the stop parameter. – vikingosegundo Jun 13 '14 at 21:53
  • Yeah it does, the answer deals with how to replace this older call with the newer syntax and how to stop it early as well. – David Berry Jun 13 '14 at 21:58
  • 3
    if we are asked to give an answer regarding a specific api, It might be helpful to give an alternate option but technically it is not an answer. only one opinion. If you are ask in a math exam to calculate some function with Taylor but you use Fourier, because ou think it is better for what reason ever, it is complete failure. if OP needs/wants to use `enumerateObjectsUsingBlock`, we shouldn't force him to use something else. though we should mention a better way. – vikingosegundo Jun 13 '14 at 22:07

5 Answers5

38

In Swift 1:

stop.withUnsafePointer { p in p.memory = true }

In Swift 2:

stop.memory = true

In Swift 3 - 4:

stop.pointee = true
user28434'mstep
  • 6,290
  • 2
  • 20
  • 35
Christian Dietrich
  • 11,778
  • 4
  • 24
  • 32
37

This has unfortunately changed every major version of Swift. Here's a breakdown:

Swift 1

stop.withUnsafePointer { p in p.memory = true }

Swift 2

stop.memory = true

Swift 3

stop.pointee = true
Sam Soffes
  • 14,831
  • 9
  • 76
  • 80
20

since XCode6 Beta4, the following way can be used instead:

let array: NSArray = // the array with some elements...

array.enumerateObjectsUsingBlock( { (object: AnyObject!, idx: Int, stop: UnsafePointer<ObjCBool>) -> Void in

        // do something with the current element...

        var shouldStop: ObjCBool = // true or false ...
        stop.initialize(shouldStop)

        })
holex
  • 23,961
  • 7
  • 62
  • 76
  • 4
    I was about to post an answer that noted that `stop[0] = true` worked, but I think I like `stop.initialize(true)` more. The lack of clear guidance on this topic (for a pattern that is used a lot) is a tad frustrating. – Rob Aug 01 '14 at 15:27
7

The accepted answer is correct but will work for NSArrays only. Not for the Swift datatype Array. If you like you can recreate it with an extension.

extension Array{
    func enumerateObjectsUsingBlock(enumerator:(obj:Any, idx:Int, inout stop:Bool)->Void){
        for (i,v) in enumerate(self){
            var stop:Bool = false
            enumerator(obj: v, idx: i,  stop: &stop)
            if stop{
                break
            }
        }
    }
}

call it like

[1,2,3,4,5].enumerateObjectsUsingBlock({
    obj, idx, stop in

    let x = (obj as Int) * (obj as Int)
    println("\(x)")

    if obj as Int == 3{
        stop = true
    }
})

or for function with a block as the last parameter you can do

[1,2,3,4,5].enumerateObjectsUsingBlock(){
    obj, idx, stop in

    let x = (obj as Int) * (obj as Int)
    println("\(x)")

    if obj as Int == 3{
        stop = true
    }
}
vikingosegundo
  • 52,040
  • 14
  • 137
  • 178
  • 1
    it does on my machine. with beta 3. – vikingosegundo Jul 15 '14 at 20:19
  • @VyachaslavGerchicov I guess your question is: "Why has this been upvoted if it doesn't work". Well, it did 4 years ago. Swift has been undergoing several incompatible changes. Fell free to fix it. – vikingosegundo Jun 19 '18 at 12:58
  • @vikingosegundo `Cannot assign to value: 'stop' is a 'let' constant`. The simplest solution I found is `stop.initialize(to: true)`. Do you know a better one which works? – Vyachaslav Gerchicov Jun 19 '18 at 13:18
-3

Just stop = true

Since stop is declared as inout, swift will take care of mapping the indirection for you.

David Berry
  • 40,941
  • 12
  • 84
  • 95