Yaroslav Yaremenko
Yaroslav Yaremenko

Reputation: 49

Swift 4: generic conforming to AnyObject does not accept a protocol conforming to AnyObject

I need to create an array of type-safe weak references

  1. a structure that holds a 'type-safe' weak reference and can be an element of an array:

    public struct WeakRef<T: AnyObject>: Hashable {
        public weak var ref: T?
        public let hashValue: Int
    
        init(_ ref: T) {
            self.ref = ref
            self.hashValue = ObjectIdentifier(ref).hashValue
        }
    }
    
    extension WeakRef: Equatable {
        public static func ==(lhs: WeakRef<T>, rhs: WeakRef<T>) -> Bool {
            return lhs.hashValue == rhs.hashValue
        }
    }
    
    extension WeakRef: Comparable {
        static public func < (lhs:WeakRef<T>, rhs:WeakRef<T>) -> Bool {
            return lhs.hashValue < rhs.hashValue
        }
        static public func <= (lhs:WeakRef<T>, rhs:WeakRef<T>) -> Bool {
            return lhs.hashValue <= rhs.hashValue
        }
        static public func >= (lhs:WeakRef<T>, rhs:WeakRef<T>) -> Bool {
            return lhs.hashValue >= rhs.hashValue
        }
        static public func > (lhs:WeakRef<T>, rhs:WeakRef<T>) -> Bool {
            return lhs.hashValue > rhs.hashValue
        }
    }
    
  2. I have a protocol which needs to be used with this weak ref:

    protocol LemmingTrackingProtocol: AnyObject {
        func onLemmingZPositionChanged()
        func onLemmingDrop()
    }
    
  3. this is possible:

    var trackers = [WeakRef<LemmingTrackingProtocol>]()
    
  4. but this is not:

    func addTracker(_ tracker: LemmingTrackingProtocol) {
        let tracker = WeakRef(tracker) // <-- Cannot invoke initializer...
    
        ...
    }
    

Please kindly give me a hint of what I am doing wrong. Thanks!

Upvotes: 2

Views: 255

Answers (1)

Yaroslav Yaremenko
Yaroslav Yaremenko

Reputation: 49

TL;DR:

just add @objc to required protocol (in my case LemmingTrackingProtocol)

Warning

though this works, you'll probably get stuck with not being able to create an extension with your @objc protocol

Detailed

according to @Hamish links provided:

  1. this is a (sort of) bug: https://bugs.swift.org/browse/SR-55, and it is still present in Swift 4
  2. protocols do not (should not) always conform to themselves

Upvotes: 1

Related Questions