13

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?

3
  • The problem is that a protocol does not conform to itself and not to any protocol that it inherits from, see stackoverflow.com/questions/33112559/… for a similar issue. In your case, the type WeakPropertyProtocol does not conform to AnyObject. Commented Mar 2, 2016 at 19:26
  • Thanks for comment, Martin. Is there any other way to specify that my WeakPropertyType is a class type without this AnyObject constraint? Commented Mar 2, 2016 at 22:52
  • Protocols can't currently require properties to be implemented as weak stored properties. stackoverflow.com/questions/47699813/… Commented Dec 8, 2017 at 15:31

4 Answers 4

4

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Compiler emits error: "'weak' cannot be applied to a property declaration in a protocol". Tested with Swift 5.7 (Xcode 14.0).
4

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.

4 Comments

It's interesting but I can't accept your answer. I don't really need to enforce weak-ness. But I need to be able to declare this property weak in class that conforms my protocol. Only property with class type can be weak and I can't find how to specify this without AnyObject constraint.
I misunderstood your question. I will update my answer.
Thank you Michael! The second one is what I need. It works good but I am concerned that weakProperty in ObjectProtocol isn't specified with weak reference. Also I need to explicitly specify a type for WeakPropertyType alias in class implementation. Anyway your solution is best for me at the moment.
I have been thinking more about your answer. I can't accept it because weak-ness of property isn't required in your solution. Yes, I already know that protocol can't enforce weak-ness for property but I like when code is self-documenting. So it's not an answer to my question about weak property requirement.
2

As Swift 5.7, bundled with Xcode 14.0, the compiler emits the error: "'weak' cannot be applied to a property declaration in a protocol"

A possible protocol limitation workaround uses a computed variable and a supplementary 'weak' variable wrapped by the computed variable.

Workaround 1: This workaround doesn't force types that apply the protocol to set the property to weak

protocol SharedInformation { var name: UIViewController? { get set } } class Country: SharedInformation { private weak var _name: UIViewController? var name: UIViewController? { get { _name } set { _name = newValue } } } 

Workaround 2: This one forces a type that applies the protocol to have the property wrapped with weak storage.

protocol SharedInformation { var name: Weak<UIViewController> { get set } } class Country: SharedInformation { var name: Weak<UIViewController> = .init() func usage() { // set name.wrappedValue = UIViewController() // get let value = name.wrappedValue } } public struct Weak<Wrapped: AnyObject> { public weak var wrappedValue: Wrapped? public init(_ value: Wrapped? = nil) { self.wrappedValue = value } } 

Comments

-1

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

1 Comment

Protocols can't currently require properties to be implemented as weak stored properties. stackoverflow.com/questions/47699813/…

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.