Swift: how to work around issue where weak variable of type 'protocol' is illegal


Answers

what is that inheritance in protocol

class in your case means that classes only can implement your protocol and not structs.

Question

After reading some posts here regarding this issue, I discovered that my protocol should inherit from 'class' in order for 'weak' to work on my delegate variable.

'weak' may only be applied to class or class-bound protocol types.

If my protocol does not inherit from 'class', does swift 'infer' that it should be weak?

Is this the de facto way for casting a variable of type 'protocol' to weak ?

What happens in terms of memory management

protocol FacebookLoginViewControllerDelegate: class {
    func facebookLoginViewControllerDidLogin(controller: FacebookLoginViewController)
}

class FacebookLoginViewController: UIViewController {

    weak var delegate: FacebookLoginViewControllerDelegate?

}



It means that you can conform to this protocol only classes, not structures or enums.




Supplemental Answer

I was always confused about whether delegates should be weak or not. Recently I've learned more about delegates and when to use weak references, so let me add some supplemental points here for the sake of future viewers.

  • The purpose of using the weak keyword is to avoid strong reference cycles (retain cycles). Strong reference cycles happen when two class instances have strong references to each other. Their reference counts never go to zero so they never get deallocated.

  • You only need to use weak if the delegate is a class. Swift structs and enums are value types (their values are copied when a new instance is made), not reference types, so they don't make strong reference cycles.

  • weak references are always optional (otherwise you would used unowned) and always use var (not let) so that the optional can be set to nil when it is deallocated.

  • A parent class should naturally have a strong reference to its child classes and thus not use the weak keyword. When a child wants a reference to its parent, though, it should make it a weak reference by using the weak keyword.

  • weak should be used when you want a reference to a class that you don't own, not just for a child referencing its parent. When two non-hierarchical classes need to reference each other, choose one to be weak. The one you choose depends on the situation. See the answers to this question for more on this.

  • As a general rule, delegates should be marked as weak because most delegates are referencing classes that they do not own. This is definitely true when a child is using a delegate to communicate with a parent. However, there are still some situations where a delegate can and should use a strong reference.

  • Protocols can be used for both reference types (classes) and non-reference types (structs, enums). So in the likely case that you need to make a delegate weak, you have to add the class keyword to the protocol so that it knows it is only to be used with reference types.

    protocol MyClassDelegate: class {
        // ...
    }
    
    class SomeClass {
        weak var delegate: MyClassDelegate?
    }

Further Study

Reading the following articles is what helped me to understand this much better. They also discuss related issues like the unowned keyword and the strong reference cycles that happen with closures.

Related




What exactly does `: class` do in a protocol declaration?

:class ensures that only classes can implement the protocol. And that's any class, not just subclasses of NSObject. @objc, on the other hand, tells the compiler to use Objective-C-style message passing to call methods, instead of using a vtable to look up functions.




Tags