Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make a weak protocol reference in 'pure' Swift (without @objc)

weak references don't seem to work in Swift unless a protocol is declared as @objc, which I don't want in a pure Swift app.

This code gives a compile error (weak cannot be applied to non-class type MyClassDelegate):

class MyClass {   weak var delegate: MyClassDelegate? }  protocol MyClassDelegate { } 

I need to prefix the protocol with @objc, then it works.

Question: What is the 'pure' Swift way to accomplish a weak delegate?

like image 661
hnh Avatar asked Jun 05 '14 17:06

hnh


People also ask

How do you make a protocol weak in Swift?

Protocols can be used for both reference types (classes) and value types (structs, enums). So in the likely case that you need to make a delegate weak, you have to make it an object-only protocol. The way to do that is to add AnyObject to the protocol's inheritance list.

What is a delegate in swift programming?

In Swift, a delegate is a controller object with a defined interface that can be used to control or modify the behavior of another object.


2 Answers

You need to declare the type of the protocol as AnyObject.

protocol ProtocolNameDelegate: AnyObject {     // Protocol stuff goes here }  class SomeClass {     weak var delegate: ProtocolNameDelegate? } 

Using AnyObject you say that only classes can conform to this protocol, whereas structs or enums can't.

like image 145
flainez Avatar answered Nov 12 '22 01:11

flainez


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. Using a weak reference for the delegate is what the documentation recommends. (But see this, too.)

  • Protocols can be used for both reference types (classes) and value types (structs, enums). So in the likely case that you need to make a delegate weak, you have to make it an object-only protocol. The way to do that is to add AnyObject to the protocol's inheritance list. (In the past you did this using the class keyword, but AnyObject is preferred now.)

    protocol MyClassDelegate: AnyObject {     // ... }  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.

  • Delegate documentation
  • Swift documentation: Automatic Reference Counting
  • "Weak, Strong, Unowned, Oh My!" - A Guide to References in Swift
  • Strong, Weak, and Unowned โ€“ Sorting out ARC and Swift

Related

  • How to make delegates in Swift
  • iOS: How To Make Weak Delegates In Swift
  • Swift delegation - when to use weak pointer on delegate
like image 36
Suragch Avatar answered Nov 12 '22 02:11

Suragch