Передавайте данные по протоколу при использовании Container для просмотра другого ViewController в Swift

Я начал работать над этим вопросом< /а> приложение. Я начал с tableView категорий:

введите здесь описание изображения

Для обмена данными я решил использовать протокол:

protocol Category {
    func data(object:AnyObject)
}

В первом ViewController есть следующий код:

class ViewController: UIViewController {

    var items:[String] = ["Desktop","Tablet","Phone"]

    let CategoriesData:Category? = nil

    override func viewDidLoad() {
        super.viewDidLoad()

        CategoriesData?.data(items)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

Во втором ViewController (tableView в контейнере) есть следующий код:

class CategoriesViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, Category  {

    @IBOutlet var table: UITableView!

    var items:[String] = []

    func data(object: AnyObject) {
        self.items = (object as? [String])!
        print(object)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

   func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.items.count
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell:TableViewCell = self.table.dequeueReusableCellWithIdentifier("SegueStage") as! TableViewCell

        cell.nameLabel.text = items[indexPath.row]
        return cell
    }
}

Для меня, видимо, все в порядке. Но на симуляторе ничего не появилось.

введите здесь описание изображения

Мой вопрос: Если Контейнер используется для представления другого viewController, поскольку передача данных по протоколам должна выполняться?


person James    schedule 11.12.2015    source источник
comment
Вы начинаете с CategoriesData как ноль. Как это когда-нибудь изменится? (Использование протокола — это хорошо, но вам все равно нужна ссылка на объект, который реализует протокол.)   -  person Phillip Mills    schedule 11.12.2015


Ответы (1)


ОТРЕДАКТИРОВАНО

Я ответил, почему решение TO:s не работает должным образом, но я только что понял, что не дал жизнеспособного ответа на то, как использовать протоколы в качестве делегатов для связи ViewController -> ViewController. Я оставлю полуответ ниже, пока кто-нибудь не сможет лучше ответить на полный вопрос.


Так как protocol используется в вашем коде, вы определяете свой протокол Category как делегат для экземпляров типа ViewController. Когда экземпляр типа ViewController инициализируется --- и, следовательно, принадлежит локально в области действия --- какого-то другого класса, экземпляр может делегировать обратные вызовы классу-владельцу.

Проблема в том, что ваш CategoriesViewController не содержит экземпляров типа ViewController. Отметим, что оба эти класса сами по себе являются подклассами UIViewController, но ни один из них не содержит экземпляров друг друга. Следовательно, ваш CategoriesViewController действительно соответствует протоколу Category благодаря реализации метода протокола data(...), но в CategoriesViewController нет экземпляра ViewController, который может выполнять обратные вызовы для этой функции. Следовательно, ваш файл компиляции кода, но как есть, метод data(...) в CategoriesViewController никогда не будет вызываться.

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


В качестве примера дизайна модель-делегат-контроллер рассмотрим некоторый пользовательский элемент управления с некоторым ключевым свойством value (например, позиция в элементе управления рейтингом), реализованный как подкласс UIView:

// CustomUserControl.swift
protocol CustomUserControlDelegate {
    func didChangeValue(value: Int)
}

class CustomUserControl: UIView {

    // Properties
    // ...
    private var value = 0 {
        didSet {
            // Possibly do something ...

            // Call delegate.
            delegate?.didChangeValue(value)
        }
    }

    var delegate: CustomUserControlDelegate?

    // ... some methods/actions associated with your user control.
}

Теперь давайте предположим, что экземпляр вашего CustomUserControl используется в контроллере представления, скажем, ViewController. Ваши функции делегата для пользовательского элемента управления можно использовать в контроллере представления для наблюдения за ключевыми изменениями в модели для CustomUserControl, так же, как вы использовали бы встроенные функции делегата экземпляров UITextFieldDelegate для UITextField (например, textFieldDidEndEditing(...)).

В этом простом примере используйте обратный вызов делегата из didSet свойства класса value, чтобы сообщить контроллеру представления, что один из его выходов имеет связанное обновление модели:

// ViewController.swift
Import UIKit
// ...

class ViewController: UIViewController, CustomUserControlDelegate {

    // Properties
    // ...
    @IBOutlet weak var customUserControl: CustomUserControl!
        // Instance of CustomUserControl in this UIViewController

    override func viewDidLoad() {
        super.viewDidLoad()
        // ...

        // Custom user control, handle through delegate callbacks.
        customUserControl.delegate = self
    }

    // ...

    // CustomUserControlDelegate
    func didChangeValue(value: Int) {
        // do some stuff with 'value' ...
    }

}
person dfrib    schedule 11.12.2015