在使用 Container 查看 Swift 中的另一个 ViewController 时按协议传递数据

Pass data by protocol while using Container to view another ViewController in 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作为通过协议传递数据应该完成?

已编辑

我回答了为什么 TO:s 解决方案没有按预期工作,但我刚刚意识到我还没有给出如何使用协议作为 ViewController 委托的可行答案 - > ViewController 沟通。在有人可能更好地回答完整问题之前,我会在下面留下一半的答案。


在您的代码中使用 protocol 的方式,您将协议 Category 定义为 实例 类型 [=12] 的委托=].当类型 ViewController 的实例在其他 class 的范围内初始化并因此在本地拥有时,该实例可以将回调委托给拥有者 class。

问题是您的 CategoriesViewController 不包含类型 ViewController 的任何实例。我们注意到,这两个 class 本身都是 UIViewController 的子 class,但其中 none 包含彼此的实例。因此,您的 CategoriesViewController 通过实现协议方法 data(...) 确实符合协议 Category,但是 CategoriesViewController 中没有 ViewController 实例可以回调到这个功能。因此,您的代码编译文件,但实际上,CategoriesViewController 中的方法 data(...) 将永远不会被调用。

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


作为模型-委托-控制器设计的一个例子,考虑一些自定义用户控件,带有一些键属性 value(例如评级控件中的位置),实现为子class 共 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(...))。

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

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

}