简体   繁体   中英

Weak property requirement in Swift protocol with associated type

I want to write a protocol with weak property requirement. Class that conforms it must be able to specify any type for this property. Also I don't want to specify an actual type, so it should be a type specified with some protocol. This code shows my idea for non-weak property:

protocol ObjectProtocol: class {
  typealias PropertyType
  var property: PropertyType {get set}
}

protocol FirstPropertyProtocol: class {}
protocol SecondPropertyProtocol: class {}

class FirstObjectImpl: ObjectProtocol {
  var property: FirstPropertyProtocol?
}

class SecondObjectImpl: ObjectProtocol {
  var property: SecondPropertyProtocol?
}

It works as expected.

I tried to do the same for weak property:

protocol ObjectProtocol: class {
  typealias WeakPropertyType: AnyObject //must be a class type
  weak var weakProperty: WeakPropertyType? {get set}
}

protocol WeakPropertyProtocol: class {}

class ObjectImpl: ObjectProtocol {
  weak var weakProperty: WeakPropertyProtocol?
}

And I got a compiler error:

Type 'ObjectImpl' does not conform to protocol 'ObjectProtocol'

Is there any way I can make this work?

I don't believe a protocol can enforce weak-ness. For example:

protocol ObjectProtocol: class {
  weak var weakProperty: AnyObject? {get set}
}

class ObjectImpl1: ObjectProtocol {
  weak var weakProperty: AnyObject?
}

class ObjectImpl2: ObjectProtocol {
  var weakProperty: AnyObject?
}

These both compile ok, even though the protocol has weak but ObjectImpl2 does not implement it.

EDIT: Is this what you're after?...

protocol ObjectProtocol: class {
  typealias WeakPropertyType: Any //must be a class type
  var weakProperty: WeakPropertyType? {get set}
}

protocol WeakPropertyProtocol: class {}

class ObjectImpl: ObjectProtocol {
  typealias WeakPropertyType = WeakPropertyProtocol
  weak var weakProperty: WeakPropertyProtocol?
}

This implementation requires use of Any rather than AnyObject, since WeakPropertyProtocol is a protocol rather than a class.

Or this?...

protocol WeakPropertyProtocol: class {}

protocol ObjectProtocol: class {
  typealias WeakPropertyType: AnyObject //must be a class type
  var weakProperty: WeakPropertyType? {get set}
}

class MyWeakClass: WeakPropertyProtocol {

}

class ObjectImpl: ObjectProtocol {
  typealias WeakPropertyType = MyWeakClass
  weak var weakProperty: MyWeakClass?
}

Either way, I think the key is in defining which class/protocol to use for WeakPropertyType .

I made it work with @objc attribute for WeakPropertyProtocol:

protocol ObjectProtocol: class {
  typealias WeakPropertyType: AnyObject //must be a class type
  weak var weakProperty: WeakPropertyType? {get set}
}

@objc protocol WeakPropertyProtocol {}

class SomeObjectImpl: ObjectProtocol {
  weak var weakProperty: WeakPropertyProtocol?
}

It's not a best solution because I concern about this note from apple doc

Note also that @objc protocols can be adopted only by classes that inherit from Objective-C classes or other @objc classes.

I can live with this restriction but I will appreciate any better solution.

Swift 4 version.
I needed my view models to conform to a protocol. They mustn't retain a coordinator object:

protocol ViewModelType {
    associatedtype CoordinatorType: AnyObject
    weak var coordinator: CoordinatorType? { get }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM