Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delegation of singleton class in Swift

How to use delegate methods of singleton/shared class? There is one singleton class having some protocol defined but I'm not getting how to access the delegate functions in other classes.

Code snippet for a reference (swift):

protocol AClassDelegate
{
  func method1()
}

class A
{
   static let shared = A()

   override init() {
     //initialisation of member variables
   }

   var delegate: AClassDelegate
   func foo() {

   }
}


class B: AClassDelegate
{
   func bar() {
      // Note: not getting call to 'foo' method of class 'A'
      A.shared.delegate = self
      A.shared.foo()
   }
}

Is this implementation correct?

like image 365
iTink Avatar asked Mar 23 '17 12:03

iTink


2 Answers

First, I'd like to point to:

1- Creating a singleton Class should contains:

private init() {}

That leads to enforce to access the class only by using its shared instance.

2- As mentioned in Max's Answer, the delegate should be optional and has a weak reference.

3- The protocol should be a type of class, as follows:

protocol AClassDelegate: class

For more information, you might want to check this Q&A.


Now, let's assume -for testing purposes- that the method1() from AClassDelegate should be get called when calling foo() from A class:

protocol AClassDelegate: class {
    func method1()
}

class A {
    private init() {}
    static let shared = A()

    weak var delegate: AClassDelegate?

    func foo() {
        print(#function)

        delegate?.method1()
    }
}

Let's implement classes that conforms to AClassDelegate:

class B: AClassDelegate {
    func bar() {
        A.shared.delegate = self
        A.shared.foo()
    }

    func method1() {
        print("calling the delegate method B Class")
    }
}

class C: AClassDelegate {
    func bar() {
        A.shared.delegate = self
        A.shared.foo()
    }

    func method1() {
        print("calling the delegate method C Class")
    }
}

Output should be:

let b = B()
b.bar()
// this will print:
/*
 foo()
 calling the delegate method B Class
 */

let c = C()
c.bar()
// this will print:
/*
 foo()
 calling the delegate method C Class
 */
like image 161
Ahmad F Avatar answered Nov 09 '22 18:11

Ahmad F


It's almost correct. You don't take into account that the singleton lives forever (unless you destroy it somewhere), but its delegate may not. So in order to avoid crashes set the delegate property to weak and optional.

weak var delegate: AClassDelegate?

This way you shouldn't care if the delegate exists or not.

like image 5
Max Pevsner Avatar answered Nov 09 '22 17:11

Max Pevsner