2
votes

Let us suppose we have a protocol

protocol MyProtocol {
    fun someFunc()
}

class AClass {
    var delegate: MyProtocol?
}

AClass doesn't care if the delegate is a class or struct. What I want is sometimes the delegate can be a class and sometimes it can be assigned to a struct.

My question is if I should make the delegate to be "weak".

If so, I have to make MyProtocol be a "class Protocol" so that the delegate has to be a class only. If not, when I assign the delegate to class, how can I avoid retain cycle?

Thanks for any hint!

2

2 Answers

3
votes

should make the delegate to be "weak"

The answer is that if MyProtocol is not restricted to classes, you cannot make it weak, the compiler won't let you.

The reason for the above is that structs are value types. There isn't a reference that can be strong or weak, because logically the entire struct is copied in when you assign the delegate.

how can I avoid retain cycle?

This means that you have got to be careful that your delegate contains no strong references back to the instance of the class. So, for instance

struct ConcreteDelegate: MyProtocol
{
    fun someFunc() {}
    var instance: AClass

    init()
    {
        instance = AClass()
        instance.delegate = self
    }
}

Causes a reference cycle. It can be broken by declaring instance as

    weak var instance: AClass! 

Alternatively, and a better solution (IMO), your protocol functions can pass the instance as a parameter so the delegate never needs to store a reference to the instance.

protocol MyProtocol {
    func someFunc(caller: AClass)
}

You'll see the above approach adopted in Cocoa in lots of places, for example with the table view data source protocol.

0
votes

I think that you forgot that struct are not reference type but a value type. Meaning that a class has a reference in the memory heap but structures, enums haven't. By remembering this fact, there is no meaning to put weak if the delegate of your protocol is a struct because it can't cause a retain cycle.

You need to worry about retain cycles when you use only classes. If your delegate of your protocol is a class put weak if you think that your class have a reference of your protocol AND your protocol can have a reference of your class put weak that's the retain cycle.

If you want to check it put deinit functions when you are testing and see if your class is correctly deinit and not kept in memory. It's basically what I know hope it will help you.