user2503846
user2503846

Reputation: 924

Identity comparison of properties in swift

I am trying to filter out instances of an object in an array (remove an observer from a list of observers to be specific):

private var observers = [ChooserObserver]()

...

func unregisterObserver(observer: ChooserObserver ) {
    observers = observers.filter { includeElement in includeElement === observer }
}

...

protocol ChooserObserver {
    var path: String { get set }
}

Unfortunately, I get the following error:

Type 'ChooserObserver' does not conform to protocol 'AnyObject'

If I attempt to allow ChooserObserver to inherit AnyObject like so:

protocol ChooserObserver: AnyObject {
    var path: String { get set }
}

I am met with the following error:

Cannot declare explicit conformance to the 'AnyObject' protocol

When I attempt to cast to AnyObject:

func unregisterObserver(observer: ChooserObserver ) {
    observers = observers.filter { includeElement in includeElement as AnyObject !== observer as AnyObject }
}

I get these errors:

Partial application of struct method is not allowed

Cannot downcast from 'ChooserObserver' to non-@objc protocol type 'AnyObject'

I can only fix by appending @objc to my protocol in conjunction with the previous cast to AnyObject:

@objc protocol ChooserObserver {
    var path: String { get set }
}

Is this necessary, and if so why? I realize that an NSMutableSet would probably be appropriate here, but I am trying to understand Swift's type system.

Upvotes: 1

Views: 459

Answers (3)

newacct
newacct

Reputation: 122429

If I attempt to allow ChooserObserver to inherit AnyObject like so: I am met with the following error:

The correct syntax is

protocol ChooserObserver : class {
    //...
}

(Probably Apple should have just allowed you to do : AnyObject to avoid needing this new syntax.)

Upvotes: 3

Kirsteins
Kirsteins

Reputation: 27335

Protocols can be conformed by both class and value types. Identical operator only works for class instances. Identical to operator must be sure both operands are classes. I guess thats why there is such limitation. Objective-C value types cannot conform to protocols, thats why @objc protocol ChooserObserver works.

Upvotes: 1

fluidsonic
fluidsonic

Reputation: 4676

Just an idea, maybe it works:

private var observerRefs = [AnyObject]()
private var observers = [ChooserObserver]()

...

func registerObserver<O where O: AnyObject, O: ChooserObserver>(observer: O) {
    observerRefs.append(observer)
    observers.append(observer)
}

func unregisterObserver<O where O: AnyObject, O: ChooserObserver>(observer: O) {
    for let index in (observerRefs.count - 1) .. 0 {
        if observerRefs[index] === observer {
            observerRefs.removeAtIndex(index)
            observers.removeAtIndex(index)
        }
    }
}

...

protocol ChooserObserver {
    var path: String { get set }
}

Upvotes: 1

Related Questions