RASS RASS - 1 year ago 76
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.)


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 Source

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
        sum += e

// sum == 6

(tested in a playground on Swift 2.2)

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download