NSView не освобождается

#swift #macos #cocoa #delegation #nsviewcontroller

#swift #macos #cocoa #делегирование #nsviewcontroller

Вопрос:

У меня здесь странная ситуация, которая почти наверняка связана с тем, что я новичок в разработке macOS и мне не хватает некоторых базовых знаний.

У меня есть модальный лист, который я отображаю программно. (Я не использую переход к раскадровке, потому что он должен быть результатом проверки, и пока я не видел способа запустить переход программно — это дополнительный вопрос здесь, если у кого-нибудь есть совет)

Вот как я это делаю:

 searchVC = NSStoryboard(name: "Main", bundle: nil).instantiateController(withIdentifier: "SearchSceneIdentifier") as? SearchViewController
    if searchVC != nil {
        searchVC!.searchTerm = searchTextField.stringValue
        self.presentAsSheet(searchVC!)
    }
  

Это красиво отображает таблицу и позволяет мне взаимодействовать с ней. В нем я использую класс, у которого есть делегат, чтобы возвращать асинхронные поисковые запросы.

Где это становится странным, так это когда я вызываю

 self.view.window!.close()
  

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

Я обошел это, сделав это перед закрытием окна:

 search.delegate = nil
  

Но это не очень хорошее решение для других контроллеров просмотра, у которых такая же проблема, потому что они находятся внутри Windows, и я не хочу перехватывать закрытие окна, а затем отправлять какое-либо уведомление каждому, чтобы свести к нулю их делегатов.

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

Все это кажется неприятным решением проблемы освобождения, и я надеюсь, что есть более чистый способ сделать это. В Objective-C подсчет ссылок всегда был проблемой, но существовали шаблоны для их точной обработки.

Приветствуются любые советы.

Комментарии:

1. В документации presentAsSheet(_:) говорится: «Чтобы закрыть лист, вызовите метод dismiss(_:) для self (представляющий контроллер представления)»..

2. Действительно, это так, спасибо. Но выполнение этого без установки для делегата значения nil приводит к тому, что контроллер представления остается выделенным и продолжает получать вызовы метода делегирования.

3. Является ли делегат владельцем ссылки на лист? Или есть что-то еще, содержащее надежную ссылку на лист?

4. Из моего тестирования кажется, что делегат — это единственное, что имеет ссылку. Однако вы используете слово «сильный» — можно ли решить эту проблему, сделав делегат слабой переменной в своем классе? В настоящее время он определен как public var delegate: SearchDelegate?

5. ваше свойство делегата должно быть слабым. Это обычный сценарий. Свойства делегата почти всегда следует объявлять слабыми из-за подобных проблем с циклом сохранения.

Ответ №1:

Я обновил все свои делегаты до weak var , и это решило все мои проблемы с освобождением.