When using Task { ... } in Swift 5.5, I'm unclear if retain cycles might be an issue or not. For example:
class ViewController: UIViewController {
private var rows = [String]()
private var tableView: UITableView?
func populateRows() {
Task {
rows = (try? await getRowsFromNetwork()) ?? []
tableView?.reloadData()
}
}
}
Will populateRows
retain the view controller for the life of the task because it references rows
and tableView
?
If the view controller goes out of scope, I'd like it to have the freedom to deallocate without populateRows
retaining it. This syntax compiles, but I don't know if it makes sense:
class ViewController: UIViewController {
private var rows = [String]()
private var tableView: UITableView?
func populateRows() {
Task { [weak self] in
self?.rows = (try? await self?.getRowsFromNetwork()) ?? []
self?.tableView?.reloadData()
}
}
}
I don't mind if the task continues to run. (I'm not worried about canceling it.) I just want to understand if there is a way to avoid retaining the view controller in the task, and if that happens automatically or if something like [weak self]
is needed.