2015-12-11 9 views
2

Я начал работу с приложением this question. Я начал Tableview категорий:Передача данных по протоколу при использовании контейнера для просмотра другого ViewController в Swift

enter image description here

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

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 in Container) есть следующий код:

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 
    } 
} 

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

enter image description here

Мой вопрос: Если использование Container представить другой ViewController в передаче данных по протоколам должно быть сделано?

+0

Вы начинаете с 'CategoriesData' как ноль. Как это изменилось? (Использование протокола в порядке, но вам все еще нужна ссылка на объект, который реализует протокол.) –

ответ

4

EDITED

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


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

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

}