使用容器查看Swift中的另一个ViewController时,按协议传递数据

使用容器查看Swift中的另一个ViewController时,按协议传递数据,swift,uiviewcontroller,swift2,swift2.1,swift-protocols,Swift,Uiviewcontroller,Swift2,Swift2.1,Swift Protocols,我开始开发这个应用程序。 我从类别的表格视图开始: 对于数据交换,我决定使用协议: protocol Category { func data(object:AnyObject) } 在第一个视图中,控制器具有以下代码: class ViewController: UIViewController { var items:[String] = ["Desktop","Tablet","Phone"] let CategoriesData:Category? = ni

我开始开发这个应用程序。 我从类别的表格视图开始:

对于数据交换,我决定使用协议:

protocol Category {
    func data(object:AnyObject)
}
在第一个视图中,控制器具有以下代码:

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.
    }
}
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中,容器中的tableView具有以下代码:

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.
    }
}
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表示为通过协议传递数据,那么应该这样做吗?

我回答了为什么TO:s解决方案不能按预期工作,但我刚刚意识到,对于如何使用协议作为ViewController->ViewController通信的代理,我还没有给出一个可行的答案。我将在下面留下半个答案,直到有人能够更好地回答完整的问题

按照在代码中使用协议的方式,您可以将协议类别定义为ViewController类型实例的委托。当ViewController类型的实例在某个其他类中初始化并因此在其作用域中本地拥有时,该实例可以将回调委托给所属类

问题是您的CategoriesViewController不包含任何ViewController类型的实例。我们注意到,这两个类本身都是UIViewController的子类,但它们都不包含彼此的实例。因此,通过实现协议方法data…,您的CategoriesViewController确实符合协议类别,但CategoriesViewController中没有可以回调此函数的ViewController实例。因此,您的代码编译文件,但实际上,方法数据。。。在CategoriesViewController中,将永远不会调用

我可能弄错了,但据我所知,协议委托用于在MVC设计中的模型和控制器的模型之间进行回调(见下面的示例),而在您的情况下,您希望在两个控制器之间直接使用委托

作为模型委托控制器设计的一个例子,考虑一些自定义用户控件,其中一些关键属性值,例如在分级控件中的位置,被实现为UIVIEW的子类:

现在让我们假设CustomUserControl的一个实例用于视图控制器,例如ViewController。自定义控件的委托函数可在视图控制器中用于观察CustomUserControl模型中的关键更改,就像您将UITextFieldDelegate的固有委托函数用于UITextField实例一样,例如TextFieldDiEndEditing

对于这个简单的示例,使用来自类属性值的didSet的委托回调来告诉视图控制器它的一个出口已经关联了模型更新:

// 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' ...
    }

}
首先,CategoriesData为nil。这有什么变化吗?使用协议是可以的,但仍然需要对实现协议的对象的引用。