23

I'm trying to mark a variable of a generic type as weak:

class X<T> {
  weak var t: T?
}

If I don't put in any constraints for T I get the error weak cannot be applied to non-class type 'T'.

If I would only use use this with NSObject derived classes this would work:

class X<T: NSObject> {
  weak var t: T?
}

But I also want to be able to use pure Swift classes.

For protocols it is possible to require that the implementor is of class type by using the class keyword:

protocol ClassType: class {
}

With the ClassType protocol I can now mark the variable as weak:

class X<T: ClassType> {
  weak var t: T?
}

But I cannot add the class keyword directly to the generic parameter:

class X<T: class> { // Compile error
  weak var t: T?
}

I can make the protocol solution work for all NSObject derived classes with an extension:

extension NSObject: ClassType {
}

But for pure Swift classes there is no common superclass that I could add this extension to. Is there a way to make this work without adding the ClassType protocol to each class I want to use the X class with? E.g. some special qualifier for the generic parameter like class X<T:ThisIsAClass>?

mfaani
  • 33,269
  • 19
  • 164
  • 293
lassej
  • 6,256
  • 6
  • 26
  • 34

1 Answers1

30

You want AnyObject, which the Swift docs describe as:

The protocol to which all classes implicitly conform.

class X<T: AnyObject> {
    weak var t: T?
}

class C { }
let x = X<C>()  // works fine
x.t = C()  

// error: type 'Int' does not conform to protocol ‘AnyObject’
// (because Int is a struct)
let y = X<Int>()
Airspeed Velocity
  • 40,491
  • 8
  • 113
  • 118
  • 5
    Is there any way to make it work with the protocol that has a class bound? (e.g. to be able to create `protocol Interface: class { }` and then create subclass `class Y: X { }`) – Tomasz Pe Jul 27 '18 at 12:39
  • 3
    **Found an answer:** You need to add the `@objc` attribute to the protocol declaration and it works as well `@objc protocol Interface: class { }` – Tomasz Pe Aug 14 '18 at 09:14