Swift MacOX - Popover segue создает несколько экземпляров контроллера представления, не уничтожая их, когда они отклоняются - PullRequest
1 голос
/ 03 апреля 2019

Я создаю контроллер раскадровки в стиле раскадровки, как этот

enter image description here

Затем я нажимаю кнопку, отображается контроллер вида, а когда я щелкаю где-либо снаружи, контроллер вида «отклоняется».

Однако, когда я снова нажимаю кнопку, запускается новый экземпляр контроллера представления, а предыдущий все еще работает. Я попытался deinit, но он не вызывается, когда контроллер представления "отклонен".

Как я могу либо уничтожить экземпляр контроллера представления при щелчке снаружи, либо "показать" уже созданный экземпляр?

Мой код в контроллере вида:

class FileTransViewController: NSViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do view setup here.
        timer = Timer.scheduledTimer(timeInterval: 0.25, target: self, selector: #selector(updateProgress), userInfo: nil, repeats: true)
        //print(123)
        print("\(self)")
    }

    deinit {
        print("destroyed")
        if let timer = timer {
            timer.invalidate()
        }
    }

    @objc func updateProgress() {
        print("updating progress")
    }

}

Ответы [ 2 ]

3 голосов
/ 03 апреля 2019

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

Чтобы разорвать цикл, вы должны сделать недействительным таймер.Вы не можете сделать это в deinit, потому что по определению его нельзя вызвать до тех пор, пока вы не разорвете цикл.NSPopover.willCloseNotification может быть хорошей возможностью.

1 голос
/ 03 апреля 2019

Как говорит @matt, у вас проблема с сохранением цикла.Вы можете избежать этого, используя Timer с блоком, где вы можете объявить weak ссылку для self

timer = Timer.scheduledTimer(withTimeInterval: 0.25, repeats: true) { [weak self] timer in
    guard let self = self else {
        timer.invalidate()
        return
    }
    print("updating progress")
}

Вам также не нужно deinit в этом случае, так как выаннулирование таймера в блоке guard else, и вам также не нужна переменная timer, и вы можете просто написать Timer, если не хотите отменять таймер вручную где-то еще

override func viewDidLoad() {
    super.viewDidLoad()
    Timer.scheduledTimer(...) { ... }
}
...