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

У меня здесь странная ситуация, которая почти наверняка связана с тем, что я новичок в разработке 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

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

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

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

Любые советы приветствуются.


person hocker    schedule 18.03.2019    source источник
comment
В документации presentAsSheet(_:) говорится, что Чтобы закрыть лист, вызовите метод отклонения (_:) для себя (представляющий контроллер представления).   -  person Willeke    schedule 18.03.2019
comment
Действительно так, спасибо. Но выполнение этого без установки делегата в nil приводит к тому, что контроллер представления остается выделенным и продолжает получать вызовы метода делегата.   -  person hocker    schedule 18.03.2019
comment
Имеет ли делегат ссылку на лист? Или есть что-то еще, удерживающее сильную связь с листом?   -  person Ron    schedule 18.03.2019
comment
Из моего тестирования кажется, что делегат — это единственное, что имеет ссылку. Однако вы используете слово «сильный» — можно ли решить эту проблему, сделав делегат слабой переменной в своем классе? В настоящее время он определен как открытый делегат var : SearchDelegate?   -  person hocker    schedule 18.03.2019
comment
Как перейти от «модального листа» к делегату?   -  person El Tomato    schedule 18.03.2019
comment
У меня есть класс поиска, в котором есть свойство делегата. Модальный лист, содержащий представление, которое я обсуждаю выше, получает сообщения от класса поиска, реализуя протокол делегата и устанавливая для делегата значение 'self'.   -  person hocker    schedule 19.03.2019
comment
ваше свойство делегата должно быть слабым. Это распространенный сценарий. Свойства делегата почти всегда следует объявлять слабыми из-за подобных проблем цикла сохранения.   -  person clarus    schedule 31.03.2019


Ответы (1)


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

person hocker    schedule 31.03.2019