Using as a concrete type conforming to protocol AnyObject is not supported

I’m using Swift 2 and using WeakContainer as a way to store a set of weak objects, much like NSHashTable.weakObjectsHashTable()

struct WeakContainer<T: AnyObject> {
    weak var value: T?
}

public protocol MyDelegate : AnyObject {

}

Then in my ViewController, I declare

  • Netty Channel closed detection
  • Why do I get the error “Protocol … can only be used as a generic constraint because it has Self or associated type requirements”?
  • Unable to use custom class in a protocol with @objc attribute?
  • Why can't I pass a Protocol.Type to a generic T.Type parameter?
  • Integration Objective C Protocols with Swift
  • swift 2.0 - UITextFieldDelegate protocol extension not working
  • public var delegates = [WeakContainer<MyDelegate>]
    

    But it is error

    Using MyDelegate as a concrete type conforming to protocol AnyObject is not supported

    I see that the error is that WeakContainer has value member declared as weak, so T is expected to be object. But I also declare MyDelegate as AnyObject, too. How to get around this?

    6 Solutions Collect From Internet About “Using as a concrete type conforming to protocol AnyObject is not supported”

    I had the same idea to create weak container with generics.
    As result I created wrapper for NSHashTable and did some workaround for your compiler error.

    class WeakSet<ObjectType>: SequenceType {
    
        var count: Int {
            return weakStorage.count
        }
    
        private let weakStorage = NSHashTable.weakObjectsHashTable()
    
        func addObject(object: ObjectType) {
            guard object is AnyObject else { fatalError("Object (\(object)) should be subclass of AnyObject") }
            weakStorage.addObject(object as? AnyObject)
        }
    
        func removeObject(object: ObjectType) {
            guard object is AnyObject else { fatalError("Object (\(object)) should be subclass of AnyObject") }
            weakStorage.removeObject(object as? AnyObject)
        }
    
        func removeAllObjects() {
            weakStorage.removeAllObjects()
        }
    
        func containsObject(object: ObjectType) -> Bool {
            guard object is AnyObject else { fatalError("Object (\(object)) should be subclass of AnyObject") }
            return weakStorage.containsObject(object as? AnyObject)
        }
    
        func generate() -> AnyGenerator<ObjectType> {
            let enumerator = weakStorage.objectEnumerator()
            return anyGenerator {
                return enumerator.nextObject() as! ObjectType?
            }
        }
    }
    

    Usage:

    protocol MyDelegate : AnyObject {
        func doWork()
    }
    
    class MyClass: AnyObject, MyDelegate {
        fun doWork() {
            // Do delegated work.
        }
    }
    
    var delegates = WeakSet<MyDelegate>()
    delegates.addObject(MyClass())
    
    for delegate in delegates {
        delegate.doWork()
    }
    

    It’s not the best solution, because WeakSet can be initialized with any type, and if this type doesn’t conform to AnyObject protocol then app will crash. But I don’t see any better solution right now.

    I ran into the same problem when I tried to implement weak containers. As @plivesey points out in a comment above, this seems to be a bug in Swift 2.2 / Xcode 7.3, but it is expected to work.

    However, the problem does not occur for some Foundation protocols. For example, this compiles:

    let container = WeakContainer<NSCacheDelegate>()
    

    I found out that this works for protocols marked with the @objc attribute. You can use this as a workaround:

    Workaround 1

    @objc
    public protocol MyDelegate : AnyObject { }
    
    let container = WeakContainer<MyDelegate>() // No compiler error
    

    As this can lead to other problems (some types cannot be represented in Objective-C), here is an alternative approach:

    Workaround 2

    Drop the AnyObject requirement from the container, and cast the value to AnyObject internally.

    struct WeakContainer<T> {
      private weak var _value:AnyObject?
      var value: T? {
        get {
          return _value as? T
        }
        set {
          _value = newValue as? AnyObject
        }
      }
    }
    
    protocol MyDelegate : AnyObject { }
    
    var container = WeakContainer<MyDelegate>() // No compiler error
    

    Caveat: Saving values that conform to T but are not AnyObjects fails.

    Why are you trying to use generics? I would suggest doing the following:

    import Foundation
    import UIKit
    
    protocol MyDelegate : AnyObject {
    
    }
    
    class WeakContainer : AnyObject {
        weak var value: MyDelegate?
    }
    
    class ViewController: UIViewController {
        var delegates = [WeakContainer]()
    }
    

    There is also NSValue‘s nonretainedObject

    Your issue is that WeakContainer requires its generic type T to be a subtype of AnyObject – a protocol declaration is not a subtype of AnyObject. You have four options:

    1. Instead of declaring WeakContainer<MyDelegate> replace it with something that actually implements MyDelegate. The Swift-y approach for this is to use the AnyX pattern: struct AnyMyDelegate : MyDelegate { ... }

    2. Define MyDelegate to be ‘class bound’ as protocol MyDelegate : class { ... }

    3. Annotate MyDelegate with @obj which, essentially, makes it ‘class bound’

    4. Reformulate WeakContainer to not require its generic type to inherit from AnyObject. You’ll be hard pressed to make this work because you need a property declared as weak var and there are limitation as to what types are accepted by weak var – which are AnyObject essentially.

    If your Protocol can be marked as @obj then you can use code below

    protocol Observerable {
    
        associatedtype P : AnyObject
    
        var delegates: NSHashTable<P> { get }
    }
    
    @objc protocol MyProtocol {
    
        func someFunc()
    
    }
    
    class SomeClass : Observerable {
    
        var delegates = NSHashTable<MyProtocol>.weakObjects()
    
    }
    

    Here is my implementation of WeakSet in pure Swift (without NSHashTable).

    internal struct WeakBox<T: AnyObject> {
        internal private(set) weak var value: T?
        private var pointer: UnsafePointer<Void>
        internal init(_ value: T) {
            self.value = value
            self.pointer = unsafeAddressOf(value)
        }
    }
    
    
    extension WeakBox: Hashable {
        var hashValue: Int {
            return self.pointer.hashValue
        }
    }
    
    
    extension WeakBox: Equatable {}
    
    func ==<T>(lhs: WeakBox<T>, rhs: WeakBox<T>) -> Bool {
        return lhs.pointer == rhs.pointer
    }
    
    
    
    public struct WeakSet<Element>: SequenceType {
        private var boxes = Set<WeakBox<AnyObject>>()
    
        public mutating func insert(member: Element) {
            guard let object = member as? AnyObject else {
                fatalError("WeakSet's member (\(member)) must conform to AnyObject protocol.")
            }
    
            self.boxes.insert(WeakBox(object))
        }
    
        public mutating func remove(member: Element) {
            guard let object = member as? AnyObject else {
                fatalError("WeakSet's member (\(member)) must conform to AnyObject protocol.")
            }
    
            self.boxes.remove(WeakBox(object))
        }
    
        public mutating func removeAll() {
            self.boxes.removeAll()
        }
    
        public func contains(member: Element) -> Bool {
            guard let object = member as? AnyObject else {
                fatalError("WeakSet's member (\(member)) must conform to AnyObject protocol.")
            }
    
            return self.boxes.contains(WeakBox(object))
        }
    
        public func generate() -> AnyGenerator<Element> {
            var generator = self.boxes.generate()
    
            return AnyGenerator {
                while(true) {
                    guard let box = generator.next() else {
                        return nil
                    }
    
                    guard let element = box.value else {
                        continue
                    }
    
                    return element as? Element
                }
            }
        }
    }