Давайте представим, у вас есть какая-то сложная задача, и вы хотите поставить обратный вызов вызываются, когда задача выполнена:
class ComplexTaskManager {
var completionHandler: (() -> Void)?
func performSomeComplexTask() {
...
// when done, call the completion handler
completionHandler?()
// if this was a one-time completion handler, you'd `nil` it; it helps protect against strong reference cycles; otherwise comment the next line
completionHandler = nil
}
}
Таким образом, вы будете использовать это нравится:
let manager = ComplexTaskManager()
manager.completionHandler = {
// this is what I want to do when the task is done
}
manager.performSomeComplexTask()
Теперь, я воображал, что мы имеем дело с каким-то трудоемкое асинхронной задачей, для которой вы хотите вызвать функцию обратного вызова, когда это сделано. Но есть и другие аналогичные шаблоны (например, возможно, вы выполняете итерацию через некоторый объект модели, и вы хотите вызвать ваш обратный вызов для каждого экземпляра внутри этого объекта), но идея такая же, как и выше.
Если у вас есть сильный опорный цикл, вы можете исправить это с помощью слабых ссылок (например, поставки [weak self]
или [unowned self]
к закрытию). Например, представьте себе:
class ViewController {
let manager = ComplexTaskManager()
@IBOutlet weak var statusLabel: UILabel!
override viewDidLoad() {
super.viewDidLoad()
statusLabel.text = "Starting complex task"
manager.completionHandler = { [weak self] in
self?.statusLabel.text = "Done"
}
manager.performSomeComplexTask()
}
}
Но вам нужно только сделать это, если есть сильный опорный цикл (например, контроллер представления держит сильную ссылку менеджеру и из-за присутствия self
внутри закрытия, то менеджер сохраняет обратную связь с контроллером представления). Если какой-либо из них являются локальными ссылками, а не свойство, хотя, нет никакого сильного опорного цикла ломаться.
Откровенно, тем более общий шаблон для закрытия, которая будет вызываться один раз за задачей является предоставить его в качестве параметра метода. Например:
class ComplexTaskManager {
func performSomeComplexTask(completionHandler:() -> Void) {
...
// when done, call the completion handler
completionHandler()
}
}
Таким образом, вы бы использовать его как:
let manager = ComplexTaskManager()
manager.performSomeComplexTask() {
// this is what I want to do when the task is done
}
Красота этого подхода заключается в том, что это не только проще, но и позволяет избежать риска сильных опорных циклов.
Попробуйте [это] (https://www.weheartswift.com/closures/) учебник – Honey
@Honey отличный учебник! – JThora