Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Run a function just after initi() completes in Swift

I am testing to run delegation pattern from initializers. Here is my data supplier test class and its’ data source :

protocol MyClassDataSource : AnyObject{
    func returnString(string: String)
}

protocol MyClassProtocol: AnyObject {
    var dataSource : MyClassDataSource? { get set }
}

class MyClass : MyClassProtocol {
    weak var dataSource: MyClassDataSource?
    
    init() {
        print("1. My Class initialized")
        getString()
    }

    func getString() {
        let myString = "Hello World"
        print("3. The getString func run")
        dataSource?.returnString(string: myString)
    }
}

I send data to my other class. Here it is :

class OtherClass : MyClassDataSource {
    
    weak var myClass : MyClassProtocol?
    
    init(myClass: MyClassProtocol?) {
        self.myClass = myClass
        self.myClass?.dataSource = self
        print("2. MyClass delegate set")
    }
    
    func returnString(string: String) {
        print("4. Delegate run and print the string: \(string)")
    }
}

Then I initialize them :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

let myClass = MyClass()
let otherClass = OtherClass(myClass: myClass)

I want to create my class and send data from MyClass to OtherClass. I wanted to use init() functions to set dataSource to self and also run a function and send data. Of course, it didn’t work. What I expected to see printed in the console :

  1. My Class initialized
  2. MyClass delegate set
  3. The getString() func run
  4. DataSource run in OtherClass and print the string: Hello World

But getString() immediately run, before setting or creating the OtherClass and prints this :

  1. My Class initialized
  2. The getString() func run
  3. MyClass delegate set

If I manually delay the getString() run, it works :

    func getString() {
        let myString = "Hello World"
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
            print("3. The getString func run")
            self?.dataSource?.returnString(string: myString)
        }
    }

So, my question is, how can I make it work? Can I set the delegate and send data between just by initializing the classes? Is it possible to do it somehow?

>Solution :

Calling getString in init is not possible. You want the data source to be set before getString is called, but getString is called in init, so there is no chance for other code to set the data source. Other code can only set the data source after init.

To achieve this sequence of events, you can call getString immediately after dataSource has been set. That is the earliest point at which you can meaningfully call getStringreturnString will not be called any time before that.

weak var dataSource: MyClassDataSource? {
    didSet { 
        print("2. MyClass delegate set")
        getString() 
    }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading