Странное поведение NSTableView и NSNotificationCenter

#macos #cocoa #swift #nstableview #nsnotificationcenter

#macos #какао #swift #nstableview #nsnotificationcenter

Вопрос:

Я получил очень странное поведение при перезагрузке данных NSTableView внутри notification observer.

 class MainWindowController: NSWindowController, NSTableViewDataSource, NSTableViewDelegate
{
    var data: String[] = []

    @IBOutlet var filesTableView: NSTableView!

    override func awakeFromNib()
    {
        super.awakeFromNib()

        NSNotificationCenter.defaultCenter().addObserver(self, selector: "droppedFiles:", name: DroppedFilesNotification.notificationName, object: nil)
    }

    func droppedFiles(notification: NSNotification!)
    {
        data  = ["123"]
        println(data.count)

        filesTableView.reloadData()
    }

    func numberOfRowsInTableView(tableView: NSTableView!) -> Int
    {
        return data.count
    }

    @IBAction func crazyTest(AnyObject)
    {
       NSNotificationCenter.defaultCenter().postNotificationName(DroppedFilesNotification.notificationName, object: self, userInfo: [DroppedFilesNotification.fileNamesParameterName: ["123"]])
    }
}
 

Отображается первый вызов функции crazyTest:

 1
 

Отображается секундный вызов функции crazyTest:

 2
3
4
 

Третий вызов функции crazyTest отображает числа 5-13.

Если бы мы удалили filesTableView.reloadData() из функции droppedFiles, тогда все работает нормально, за исключением того, что представление таблицы не обновляется. Есть идеи, почему это происходит и как перезагрузить там табличное представление?

Редактировать:

Кроме того, нет проблем в случае, если вызов функции droppedFiles напрямую вместо использования NSNotificationCenter. Но я бы предпочел использовать центр уведомлений в своем приложении.

Заранее спасибо.

Ответ №1:

Если это табличное представление на основе представления, которое (возможно, неявно) загружает свои представления из NIBS, то его awakeFromNib метод будет вызываться каждый раз при загрузке NIB. Отсюда:

Примечание: Вызов makeViewWithIdentifier:owner: приводит awakeFromNib к многократному вызову вашего приложения. Это происходит потому makeViewWithIdentifier:owner: , что загружается перо с переданным владельцем, и владелец также получает awakeFromNib вызов, даже если он уже активирован.

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

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

1. Спасибо, Кен! Я не знаю, как пропустил эту заметку 😉

Ответ №2:

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