Class-only generic constraints in Swift
Asked Answered
S

1

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>?

Southwestwards answered 5/3, 2015 at 18:16 Comment(0)
K
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>()
Kirstenkirsteni answered 5/3, 2015 at 18:21 Comment(2)
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<Interface> { })Hubey
Found an answer: You need to add the @objc attribute to the protocol declaration and it works as well @objc protocol Interface: class { }Hubey

© 2022 - 2024 — McMap. All rights reserved.