Концепция использования обработчиков завершения в порядке. Вся суть обработчиков завершения заключается в том, что они предназначены для того, чтобы функция выполнялась асинхронно, предоставляя какой-то обратный вызов для запуска позже, когда функция завершилась. Речь идет не о том, слишком часто вы используете обработчики завершения. Речь идет о том, как часто вы выполняете асинхронные задачи. Ваше использование обработчиков завершения обычно будет напрямую коррелировать с количеством задач, выполняемых вашей программой, которые необходимо выполнить асинхронно.
Подобно тому, как, например, есть несколько мест, где вы, вероятно, хотите использовать асинхронные обработчик завершения в приложении IOS:
UI анимация (например UIView.animate(withDuration:animations:)
)
Сети вызовов (например URLRequest
или Data(contentsOf:options:)
)
операции CoreData (например, NSManagedObjectContext.fetch(_:)
), хотя часто даже это достаточно быстро, чтобы выполнять синхронно без обработчика завершения
и более
Все, что имеет время обработки, достаточное для «замораживания» пользовательского интерфейса для пользователя, способного восприниматься людьми.
Ваша примерная функция - это случай, когда достаточно простого возвращаемого значения.
func fetchObject(name: String!, completionHandler: @escaping (_ success: Array<String>?) -> Void) {
let objArray = ["one", "two", "three", name] //NOTE THIS IS A SILLY FUNCTION EXAMPLE BUT GETS THE STRUCTURE POINT ACROSS
completionHandler(objArray)
}
может быть преобразована в:
func fetchObject(name: String!) -> Array<String> {
let objArray = ["one", "two", "three", name] //NOTE THIS IS A SILLY FUNCTION EXAMPLE BUT GETS THE STRUCTURE POINT ACROSS
return objArray
}
Эти две функции приводят в точности то же самое. Они просто реализованы несколько иначе.Случай, когда обработчик завершения бы (теоретически) смысл будет, если функция выглядела вместо так:
func fetchObject(name: String!, completionHandler: @escaping (_ success: Array<String>?) -> Void) {
DispatchQueue.main.async(execute: {() -> Void in
let objArray = ["one", "two", "three", name] //NOTE THIS IS A SILLY FUNCTION EXAMPLE BUT GETS THE STRUCTURE POINT ACROSS
completionHandler(objArray)
})
}
Поскольку функция использует другую нить, использование обработчика завершения имеет больше смысла, так как функция является больше не синхронно. Так там, где раньше это было бы действительно:
var result: Array<String> = Array<String>()
fetchObject(name: "name", completionHandler: { (otherResult) -> Void in
result = otherResult ?? []
})
let first = result.first //first contains "one" when function is synchronous
//first contains nil when function is asynchronous (DispatchQueue)
Если мы выполняем тело функции асинхронно, то это уже не будет иметь силу, поскольку let first = result.first
будет выполняться перед result
когда-либо успешно назначен otherResult
.
Конечно, имейте в виду, что в конце концов это полностью зависит от вас. Преимуществом обработчиков завершения является их способность выполнять асинхронно. В некоторых случаях, если они функционально не нужны, он просто добавляет ненужную многословие. Однако это зависит от личных предпочтений, так как ясно, что они могут быть реализованы для получения точного результата.
Дайте мне знать, если это имеет смысл. Я могу уточнить по запросу.
Концепция использования обработчиков завершения в порядке. Вся суть обработчиков завершения заключается в том, что они предназначены для того, чтобы функция выполнялась асинхронно, предоставляя какой-то обратный вызов для запуска позже, когда функция завершилась. Речь идет не о том, слишком часто вы используете обработчики завершения. Ваше использование обработчиков завершения обычно будет напрямую коррелировать с количеством задач, выполняемых вашей программой, которые необходимо выполнить асинхронно. –
Хммм это очень полезно, поэтому я полагаю, что я принципиально использую их НЕПРАВИЛЬНО. Скорее я должен использовать возвращаемые значения, а затем проверять, является ли возвращаемое значение нулем или не заполнять мой пользовательский интерфейс. (Очевидно, что для чувствительных к времени функций) – Jerland2
Это идея. Как пример, есть несколько мест, где вы хотели бы использовать асинхронные обработчики завершения в приложении iOS: анимация пользовательского интерфейса (например, 'UIView.animate (withDuration: _ :)'), сетевые вызовы (например, 'URLRequest' или даже 'Data (contentsOf:)'), возможно, операции CoreData (например, 'NSManagedObjectContext.fetch (_ :)') и т. Д. Все, что имеет время обработки достаточно долго, чтобы «заморозить» пользовательский интерфейс для пользователя, , –