Find delegate in swift array of delegates

I want to check if I already have a delegate in my removeDelegate method before removing. How should I do it?

Here's what I have so far:

protocol LocationManagerDelegate {
    func locationManagerDidUpdateLocation(
        oldLocation: CLLocationCoordinate2D,
        currentLocation: CLLocationCoordinate2D
    )
}

class LocationManager: NSObject {
    private var _delegates = [LocationManagerDelegate]()

    func removeDelegate(delegate:LocationManagerDelegate) {
        if contains(_delegates, delegate) {
            // Remove delegate
        }
    }
}

      

However, this gives me the following error on the "if contains" line:

cannot call "contains" with an argument list of type "(@lvalue Array <LocationManagerDelegate>!, LocationManagerDelegate) '

+3


source to share


2 answers


Update for Swift 3:

Assuming delegates are actually instances of the class, you can require that in the protocol "inherit" from "class":

protocol LocationManagerDelegate: class {
    // ...
}

      

and then use the method index(where:)

using the "indentitiy operator ===

:

class LocationManager: NSObject {
    private var _delegates = [LocationManagerDelegate]()

    func removeDelegate(delegate:LocationManagerDelegate) {
        if let index = _delegates.index(where: { $0 === delegate }) {
            _delegates.remove(at: index)
        }
    }
}

      


Old answer (Swift 1):

There are two slightly different functions contains()

:

func contains<S : SequenceType where S.Generator.Element : Equatable>(seq: S, x: S.Generator.Element) -> Bool

func contains<S : SequenceType, L : BooleanType>(seq: S, predicate: (S.Generator.Element) -> L) -> Bool

      



You use the first one, which requires sequence items to conform to the protocol Equatable

, i.e. they can be compared with ==

.

Assuming delegates are actually instances of the class, you can require that in the protocol "inherit" from "class":

protocol LocationManagerDelegate : class {
    // ...
}

      

and then use the second version contains()

based on predicates using the identity operator ===

:

func removeDelegate(delegate:LocationManagerDelegate) {
    if contains(_delegates, { $0 === delegate }) {
        // Remove delegate
    }
}

      

To remove an object from an array you will need to get its index so you can use findIdenticalObject()

from fooobar.com/questions/2185739 / ... :

func findIdenticalObject<T : AnyObject>(array: [T], value: T) -> Int? {
    for (index, elem) in enumerate(array) {
        if elem === value {
            return index
        }
    }
    return nil
}

      

and then find and remove from the array with

func removeDelegate(delegate:LocationManagerDelegate) {
    if let index = findIdenticalObject(_delegates, delegate) {
        _delegates.removeAtIndex(index)
    }
}

      

+9


source


The arguments contains

must implement the Equatable protocol as it is defined as:

public func contains<T:Equatable>(left:[T], right:T) -> Bool

      

Since there is no way to specify what LocationManagerDelegate

implements Equatable, I don't think you can use it. An obvious attempt:

protocol LocationManagerDelegate : Equatable {
    ...
}

      



But it will fail when trying to declare an array, because Equatable uses Self.

Best option I can think of:

func removeDelegate(delegate:LocationManagerDelegate) {
    _delegates = filter(_delegates) { return $0 !== delegate }
}

      

+1


source







All Articles