RASS RASS - 6 months ago 18
Objective-C Question

Best way to implement pointer in Swift

In Objective-C it is quite common to use boolean pointers to stop an enumeration e.g.:

[myArray rh_iterate:^(id element, int index, BOOL *stop){
// Do cool stuff
*stop = YES;
}];


I've implemented this like:

// This is in a category of NSArray
- (void)rh_iterate:(void (^)(id, int, BOOL *))block
{
if (!block) { return; }

BOOL stop = NO;
for (int i = 0; i < self.count; i++) {
block(self[i], i, &stop);
if (stop) { return; }
}
}


I'm now implementing my version of this in Swift but am not relying on any Objective-C source code. I know that swift likes to restrict the access of pointers so what's the best way to go about implementing this? (Ideally completely avoiding pointers.)

EDIT:

The most direct way is:

func rh_iterate(callback: (Element, Int, UnsafeMutablePointer<Bool>) -> ()) {

var stop: Bool = false
for (index, element) in self.enumerate() {
callback(element, index, &stop)
if stop { return }
}
}

Answer

Since AMomchilov deleted his answer, I'll put it back.

The direct equivalent to the BOOL* pattern would be an inout variable

extension Array
{
    func iterateWithStop(closure: (Element, inout shouldStop: Bool) -> ()) -> Bool
    {
        var shouldStop = false
        for e in self
        {
            guard !shouldStop else { return false }
            closure(e, shouldStop: &shouldStop)
        }
        return !shouldStop
    }
}

The function returns true if the iteration completed without the closure trying to stop it, false if the closure did try to stop it.

You would use it like this:

let myArray = [1, 2, 3,  -1, 4]

var sum = 0
let didProcessAllElements = myArray.iterateWithStop{ e, shouldStop in
    if e < 0 
    {
        shouldStop = true
    }
    else
    {
        sum += e
    }
}

// sum == 6

(tested in a playground on Swift 2.2)