Как создать слабый делегат без вызова «Экземпляр будет немедленно освобожден, потому что свойство tableViewDelegate является« слабым »» - PullRequest
0 голосов
/ 02 марта 2019

Я пытаюсь выделить источник данных моего tableView в отдельный объект делегата.Поскольку этот делегат должен получить доступ к табличному представлению в какой-то момент, мне нужна ссылка на делегирующий объект в делегате;и поскольку оба являются классами, мне нужно избегать циклов сильных ссылок, делая делегат weak

. Для этого я попробовал следующий код.

class MyViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!
    weak var tableViewDelegate: UITableViewDataSource?

    override func viewDidLoad() {
        super.viewDidLoad()
        tableViewDelegate = TableViewDelegate() // throwing a warning
        tableView.dataSource = tableViewDelegate
    }
}

Когда я пытаюсь создать экземпляр делегатаXCode выдает предупреждение: «Экземпляр будет немедленно освобожден, потому что свойство« tableViewDelegate »является« слабым »»

Поэтому, чтобы исправить это, я делаю следующее:

class MyViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!
    weak var tableViewDelegate: UITableViewDataSource?

    override func viewDidLoad() {
        super.viewDidLoad()
        let delegate = TableViewDelegate() // worried this creates a strong reference.
        self.tableViewDelegate = delegate
        tableView.dataSource = delegate
    }
}

Пожалуйста, подтвердите, если следующееверно это или нет: инициализируя делегат в методе viewDidLoad (), я не рискую создать сильную ссылку, потому что переменная, которая содержит этот экземпляр, освобождается, как только мы покидаем область действия этого метода.Или, говоря иначе: единственное время, когда нам нужно беспокоиться о том, что переменная (которая указывает на класс) создает сильную ссылку, это если переменная инициализируется на уровне класса и, следовательно, будет жить так же долго, как и класс.,

Это правильно?

1 Ответ

0 голосов
/ 02 марта 2019

Пожалуйста, подтвердите, верно ли следующее: инициализируя делегат в методе viewDidLoad (), я не рискую создать сильную ссылку, потому что переменная, которая содержит этот экземпляр, освобождается, как только мы уходимобласть применения этого метода.

Правильно.Строгое указание исчезает, как только выходит из области действия, в которой объявлен let.

К сожалению, это означает, что ваш делегат все еще будет освобожден.Все, что вы сделали, это заставили замолчать предупреждение.

По сути, вам нужно иметь сильную ссылку на делегата где-то , иначе он сразу исчезнет.Я чувствую, что вы должны сделать ссылку в MyViewController сильной.Цикла строгой ссылки не будет, если ваш делегат не содержит строгой ссылки на контроллер представления.Если вам нужна ссылка на MyViewController в делегате, сделайте его слабым, т. Е. Контроллеру представления принадлежит делегат, а не делегату принадлежит контроллер представления.


Ответ на комментарий ниже:

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

Да, это довольно стандартная практика,Есть исключения, в том числе и в какао.Однако стандартная практика - иметь слабую ссылку на делегат в делегирующем объекте .В вашем случае делегирующим объектом является w UITableView, а не MyViewController.В вашем первом примере из Интернета FileImporter аналогичен UITableView в вашем коде.Во втором примере DetailViewController является делегирующим объектом.

Если подумать, ваш TableViewDelegate используется вместо того, чтобы MyViewController соответствовать протоколу.Совершенно очевидно, что MyViewController будет владельцем делегата.

...