0

Is it wrong to call async from Swift object initializer such as this one

let serialQueue = DispatchQueue(label: "com.myApp.SerialQueue")
private let property1:Int?

public override init()
{
    super.init()
    /* Initialize properties */
    setupProperties()
    serialQueue.async { [unowned self] in
       self.nonBlockingSetup()
    }
}
private func setupProperties() {
    self.property1 = 1
}
private func nonBlockingSetup() {
    //Some non-blocking code that shouldn't run on main thread
}

Some people say async call is problematic before init returns. Need to know what Swift language says about it.

EDIT: Is there any difference if I modify the code as follows:

public override init()
{
    super.init()
    /* Initialize properties */
    setupProperties()
    callNonBlockingCodeAsync()
}

private func callNonBlockingCodeAsync() {
   serialQueue.async { [unowned self] in
       self.nonBlockingSetup()
    }
}
3
  • 1
    Is this related to stackoverflow.com/q/62820455/1187415 ? Commented Jul 10, 2020 at 6:41
  • 1
    Yes, but it's not an answer to that question. It came out separately which I didn't get completely. So thought of putting it as a separate question. Commented Jul 10, 2020 at 6:53
  • @DeepakSharma No, you can't do that, calling super.init before initialising property of calling class is not allowed. There won't be any difference. Commented Jul 10, 2020 at 7:31

2 Answers 2

1

To answer your question, I tried out the simple example.

enter image description here

Errors are very much self explanatory, in the initialisation process dispatchQueue are capturing self reference right before it's actual initialisation.

You are running into the concurrency problem where initialisation of object is necessary before using it.

dispatchQueue uses closures to provide DispatchWorkItem and as you know closures captures values surrounding it's scope.

Update

One work around would be to give default values to your properties but I am not sure if that will help you.

Sign up to request clarification or add additional context in comments.

Comments

1

In general, a constructor should not do any meaningful work.

Having a constructor that executes code delayed (because it's async) will be unexpected for anyone using that class (quite possibly including you in 6 months), and can therefore lead to bugs. In such cases it's usually better to have a separate initialization method, which makes it clear to an api user that there is something more going on.

If you absolutely want to make sure the initialization method is called, I usually make the constructor private and add a class method for construction. Again this signals api users that there is something going on behind the scenes.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.