Как получить доступ и обновить UITableView из другого класса в Swift

У меня есть приложение панели вкладок и вкладка, контроллер представления которой контролируется классом UITableView. У меня есть класс, который используется для загрузки данных с сервера, который затем сохраняет их в NSDefaults. Оттуда я хочу, чтобы класс мог обновлять табличное представление, но я не уверен, как получить доступ к классу табличного представления, чтобы обновить его.

class updates {

func checkForUpdates() {
    //start on background thread
    dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) { [unowned self] in
        //start contacting database:
        UIApplication.sharedApplication().networkActivityIndicatorVisible = true
        let actualVersion = self.contactForUpdates()
        UIApplication.sharedApplication().networkActivityIndicatorVisible = false
        if actualVersion > self.defaults.objectForKey("version") as! Int {
            //update data
            if self.downloadUpdates() {
                //update version number
                self.defaults.setObject(actualVersion, forKey: "version")
                //Indicates progress finished
                //self.stopSpinner()
            }
        }//end updates
        else {
            //Indicates progress finished
            //self.stopSpinner()

        }
    }//end background queue
}

}

Есть две области, прокомментированные//Indicates progress finished где я хочу запустить tableView из класса:

class connectTableVC: UITableViewController {
    ...
}

Ответы на вопрос(4)

Решение Вопроса

что самый простой способ сделать то, что вы хотите сделать, это использовать делегата.

protocol UpdateDelegate {
    func didUpdate(sender: Updates)
}

Итак, в вашем классе обновлений, где вы хотите обновить табличное представление, вы бы вызвали делегатскую функцию didUpdate. (Вам нужно будет установить делегат до того, как он запустит обновление для вызываемого метода.) Важным является слабое ключевое слово, если его там нет, ни один из классов не будет GC'd, что приведет к утечкам памяти ,

class Updates {
   weak var delegate: UpdateDelegate?

   ...

    //Indicates progress finished
    self.delegate.didUpdate(self)

В вашем классе tableView вы бы подписались на этот делегат, добавив UpdateDelegate в начало класса

class ConnectTableVC: UITableViewController, UpdateDelegate {
    ...

    let updates = Updates()
    updates.delegate = self

    ...
    func didUpdate(sender: updates) {
       dispatch_async(dispatch_get_main_queue()) {
          self.tableView.reloadData()
       }
    }
 }

Я бы порекомендовал не использовать NSNotificationCenter, основная причина в том, что кто-нибудь может прослушать уведомление (что может быть маловероятным в вашем случае, но все же стоит отметить).

 Alec O28 мая 2016 г., 00:56
где бы вы предложили разместить протокол updateDelegate
 Alec O28 мая 2016 г., 00:47
Это было очень полезно и облегчило понимание делегатов. Я реализую это сейчас.
 SeanRobinson15928 мая 2016 г., 06:37
Мне нравится помещать все в отдельные файлы. Поэтому я бы поместил протокол в отдельный файл.

ть делегирование. Делегирование - это очень распространенный шаблон в iOS, вы используете его с UITableViewDataSource. Ваш контроллер представления является делегатом UITableView, то есть он соответствует протоколу UITableViewDataSource. Итак, что вы должны сделать, это создать протокол для вашегоUpdates класс как это:

protocol UpdatesDelegate {
    func didFinishUpdates(finished: Bool)
}

ВашUpdates класс будет иметь свойство делегата, соответствующее этому протоколу:

class Updates {
    var delegate: UpdatesDelegate?

Затем вы помещаете эту строку, где//indicates progress finished комментарий был:

self.delegate?.didFinishUpdates(finished: true)

ВашConnectTableViewController будет соответствовать протоколу и перезагрузить представление таблицы оттуда:

extension ConnectTableViewController: UpdatesDelegate {
    func didFinishUpdates(finished: Bool) {
        guard finished else {
            // Handle the unfinished state
            return 
        }
        self.tableView.reloadData()
    }
}

Где бы вы ни создали свой экземплярUpdates класс, не забудьте установить свойство делегата для вашегоConnectTableViewController.

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

Для Swift 3

NotificationCenter.default.post(name: NSNotification.Name(rawValue: "newDataNotificationForItemEdit"), object: nil)

NotificationCenter.default.addObserver(self, selector: #selector(self.shouldReload), name: NSNotification.Name(rawValue: "newDataNotificationForItemEdit"), object: nil)

func shouldReload() {
    self.tableView.reloadData()
}

protocol или жеNSNotificationCenter

ПримерNSNotificationCenter :

ОтUIViewController что загружает данные, вы можете опубликовать уведомление после окончания загрузки данных и сообщить другим объектам, что есть новые данные:

NSNotificationCenter.defaultCenter().
                    postNotificationName("newDataNotif", object: nil)

И любой другой объект, который хочет прослушать это уведомление, должен зарегистрироваться для наблюдения (в вашем случаеUITableViewController):

NSNotificationCenter.defaultCenter().
                     addObserver(self, #selector(shouldReload), 
                     name:"newDataNotif", object: nil)

а затем вам нужно реализовать метод, который будет вызываться при получении уведомления:

func shouldReload() {
  self.tableView.reloadData()
}

Обратите внимание, что уведомление может отправлять данные также типа[NSObject : AnyObject]? пример:

NSNotificationCenter.defaultCenter().
                     postNotificationName("newDataNotif", 
                     object: nil, userInfo: ["data":[dataArray]])

И наблюдатель будет как:

NSNotificationCenter.defaultCenter().
                     addObserver(self, #selector( shouldReload(_:)),
                     name:"newDataNotif", object: nil)

И метод, как:

func shouldReload(notification:NSNotification) {
  println(notification.userInfo)
}

и, наконец, в вашемdeinit Вы должны удалить наблюдателя:

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}
 Alec O28 мая 2016 г., 02:26
У меня были проблемы с реализацией делегатов, потому что класс обновления вызывается из контроллера представления UITabController вместо отдельных вкладок. Это было просто и быстро. Спасибо.
 Jay Mehta14 янв. 2017 г., 18:34
Я использую этот код для обновления моего NSCollectionView. Он работает идеально, как и хотел, но только обновления данных, нет никаких изменений или обновлений в collectionView.

Ваш ответ на вопрос