Асинхронный вызов очереди отправки инициализатора Swift - PullRequest
0 голосов
/ 10 июля 2020

Неправильно ли вызывать asyn c из инициализатора объекта Swift, такого как этот

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
}

Некоторые люди говорят, что вызов asyn c проблематичен c перед возвратом init. Необходимо знать, что говорит об этом язык Swift.

EDIT: есть ли разница, если я изменю код следующим образом:

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

private func callNonBlockingCodeAsync() {
   serialQueue.async { [unowned self] in
       self.nonBlockingSetup()
    }
}

Ответы [ 3 ]

1 голос
/ 10 июля 2020

Чтобы ответить на ваш вопрос, я попробовал простой пример.

введите описание изображения здесь

Errors в значительной степени говорят сами за себя, в процессе инициализации dispatchQueue захватывают ссылку на себя прямо перед ее фактической инициализацией.

Вы запускаете concurrency problem, где инициализация объекта необходима перед его использованием.

dispatchQueue использует замыкания для предоставления DispatchWorkItem, и, как вы знаете, замыкания захватывают значения, окружающие его область действия.

Обновление

Одним из способов решения проблемы было бы присвоение вашим свойствам значений по умолчанию, но я не уверен, поможет ли вам это.

1 голос
/ 10 июля 2020

В общем, конструктор не должен выполнять какой-либо значимой работы.

Наличие конструктора, который выполняет отложенный код (потому что он asyn c), будет неожиданным для всех, кто использует этот класс (вполне возможно, включая вас в 6 месяцев) и, следовательно, может привести к ошибкам. В таких случаях обычно лучше иметь отдельный метод инициализации, который дает понять пользователю api, что происходит что-то еще.

Если вы абсолютно уверены, что вызывается метод инициализации, я обычно сделайте конструктор закрытым и добавьте метод класса для построения. Это снова сигнализирует пользователям api о том, что что-то происходит за кулисами.

0 голосов
/ 10 июля 2020

Вы не должны делать асинхронные c вещи в init(). Предполагается, что вы инициализируете объекты в init(), и это все, что вы должны здесь делать. Все остальное должно выполняться в каком-то другом вызове, когда self полностью существует.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...