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.