1

I have been trying to implement an iOS app in Swift from Big Nerd Ranch's most recent iOS book.

In the guide, there is the following method, where privateItems is an NSMutableArray

- (void)removeItem:(BNRItem *)item
{
    [self.privateItems removeObjectIdenticalTo:item]
}

So in my Swift implementation, which has privateItems as a Swift Array, I would like to be able to do this:

func removeItem(item: Item) {
    _privateItems.removeObjectIndenticalTo(item)
}

However, the Swift Array does not support that method. It has the removeAtIndex method. I know that I could simply achieve the same effect with the following code:

func removeItem(item: Item) {
    for (index, element) in enumerate(_privateItems) {
        if element === item {
            _privateItems.removeAtIndex(index)
        }
    }
}

However, I would like to create a generic extension for the Swift Array so that I don't have to do this every time. Not a huge deal, but I think it would at least be good for the sake of learning.

I have looked into a couple of other SO posts (How can I extend typed Arrays in Swift? and How can we create a generic Array Extension that sums Number types in Swift?), but have not been able to accomplish what I want. Here is my attempt:

protocol Identifiable {
    func ===(lhs: Self, rhs: Self) -> Self
}

extension Array {
    func removeObjectIndenticalTo<T: Identifiable>(object: T) {
        for (index, element) in enumerate(self) {
            if object === element {
                removeAtIndex(index)
            }
        }
    }
}

I think I am pretty close. This gives the error "Could not find an overload for '===' that accepts the supplied arguments". What should I change to accomplish that?

Also for reference, there was another SO post that extended the Swift Array with some of the NSMutableArray methods in the following fashion:

extension Array {
    func contains(#object:AnyObject) -> Bool {
        return self.bridgeToObjectiveC().containsObject(object)
    }
    func indexOf(#object:AnyObject) -> Int {
        return self.bridgeToObjectiveC().indexOfObject(object)
    }
}
Community
  • 1
  • 1
SchoonSauce
  • 291
  • 1
  • 3
  • 14
  • Is Item a Struct or a Class? `===` and `!==` are for reference types only – Christian Dietrich Jun 19 '14 at 17:56
  • Note that the equivalent of indexOfObject would use the == operator. indexOfObject invokes isEqual on each object, the equivalent of the == operator. === will only match identical occurrences (pointer comparison vs. content comparison) – David Berry Jun 19 '14 at 19:01

1 Answers1

1
protocol Identifiable {
    @infix func ===(a: Self, b: Self) -> Bool
}

struct Item : Identifiable {
    var n : Int
}

@infix func ===(a: Item, b: Item) -> Bool {
    return a.n == b.n
}
var _privateItems = [Item(n:1),Item(n:2),Item(n:2),Item(n:1),Item(n:2)]
func removeItem(item: Item) {
    var tbr : Int[] = []
    for (index, element) in enumerate(_privateItems) {
        if element === item {
            tbr += index
        }
    }
    for i in reverse(sort(tbr)) {
        _privateItems.removeAtIndex(i)
    }
}
removeItem(Item(n:2))

println(_privateItems.count)
removeItem(Item(n:1))
println(_privateItems.count)
Christian Dietrich
  • 11,778
  • 4
  • 24
  • 32