在使用 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 属性 value
的 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' ...
}
}
我开始开发
为了数据交换,我决定使用协议:
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 属性 value
的 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' ...
}
}