与ViewController分开的控制器的UITableView

我是Swift和XCode的新手,今年夏天参加了iOS开发课。 我们正在做的很多项目以及我看到的像PickerViews,TableViews等UI元素的例子都在ViewController.swift文件中定义了一切,这些文件充当主视图的控制器。 这工作正常,但我开始到项目复杂的地步,我真的很喜欢我所有的代码不被塞进同一个Swift文件。 我已经和一位做iOS开发的朋友聊过了,他说这是合理的,合理的,并且适合面向对象的编程…但是我似乎无法完成它的工作。 通过试验和错误,我已经到了这种情况:应用程序在模拟器中运行,UITableView出现,但我没有得到它与项目填充。 当所有代码都在ViewController中时,我可以很好的工作,但是一旦我开始尝试创build一个新的控制器类并且创build这个类的一个实例,那么UITableView的dataSource / delegate就不会得到任何东西。 我觉得我要么在这里错过了对Swift的一些核心理解,要么在XCode的Interface Builder中做了一些错误的事情。

我的最终结果应该是一个UITableView有三个条目; 目前我得到一个没有条目的UITableView。 我跟着一些不同的例子,我已经谷歌search,但主要是这个其他的SO问题: UITableView示例为Swift

ViewController.swift:

import UIKit class ViewController: UIViewController{ @IBOutlet var stateTableView: UITableView! override func viewDidLoad() { super.viewDidLoad() var viewController = StateViewController() self.stateTableView.delegate = viewController self.stateTableView.dataSource = viewController } } 

StateViewController.swift:

 import UIKit class StateViewController: UITableViewController{ var states = ["Indiana", "Illinois", "Nebraska"] func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return states.count; } func tableView(cellForRowAttableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = UITableViewCell(style:UITableViewCellStyle.default, reuseIdentifier:"cell") cell.textLabel?.text = states[indexPath.row] return cell } } 

在XCode中,我将UITableView连接到View Controller; 这些出口设置为dataSourcedelegate ,引用出口是stateTableView

我没有得到任何错误; 我在ViewController.swift的`var viewController = StateViewController()'语句中得到了一个警告,我希望我使用一个常量,但是把它切换到一个常量不会改变行为(这是我应该做的,承担)。

本来我认为这个错误是在我的StateViewController.swift文件中,我没有创build一个符合UITableViewDataSource或UITableViewDelegate协议的对象,但是如果我甚至将它们添加到类语句中,我立即会得到如下错误:“冗余一致性'StateViewController'协议'UITableViewDataSource'“ – 我读这是因为从UITableViewControllerinheritance自动inheritance其他协议。

我试过的最后一件事情是在StateViewController的tableView函数中引用self.states ,但我很确定Swift中的self与Python中的一样,并且感觉就像我只是想在这个时候添加魔术字点。

我已经调查,据我目前有限的斯威夫特知识可以带我,所以任何答案,解释我做错了,而不是告诉我什么修复将非常感激。

你的问题是由内存pipe理问题造成的。 你有以下代码:

 override func viewDidLoad() { super.viewDidLoad() var viewController = StateViewController() self.stateTableView.delegate = viewController self.stateTableView.dataSource = viewController } 

考虑一下viewControllervariables的生命周期。 它到达viewDidLoad的末尾时结束。 而且由于表视图的dataSourcedelegate属性weak ,一旦viewDidLoad结束,没有强大的引用来保持你的StateViewController活动。 由于引用较弱,结果是在达到viewDidLoad结束后,表视图的dataSourcedelegate属性恢复为nil

解决scheme是创build一个强大的参考您的StateViewController 。 通过添加属性到你的视图控制器类来做到这一点:

 class ViewController: UIViewController{ @IBOutlet var stateTableView: UITableView! let viewController = StateViewController() override func viewDidLoad() { super.viewDidLoad() self.stateTableView.delegate = viewController self.stateTableView.dataSource = viewController } } 

现在你的代码将工作。

一旦你得到了这个工作,请查看Ahmed F.的答案绝对没有理由为什么你的StateViewController类应该是一个视图控制器。 从任何意义上讲,这不是一个视图控制器。 它只是一个实现表视图数据源和委托方法的类。

你正试图将UITableView的数据源和委托设置为UITableViewController 。 正如@Ahmad提到它更容易理解在相同的类即ViewController,你可以采取清晰的方法分离数据源和UITableViewUIViewController委托。 您可以优先使用NSObject的子类,并将其用作UITableView数据源和页面类。

你也可以使用container view并embedded一个UITableViewController 。 所有的表视图代码将移动到您的UITableViewController子类。因此,从您的视图控制器隔离您的表视图逻辑

希望能帮助到你。 快乐编码!

尽pipe我发现在同一个viewcontroller中实现dataSource / delegate方法更具可读性和可理解性,但是你试图存档的内容也是有效的。 然而, StateViewController类不一定是UITableViewController的子类(我认为这是你误解它的一部分),例如(从另一个答案适应我):

 import UIKit // ViewController File class ViewController: UIViewController { var handler: Handler! @IBOutlet weak var tableView: UITableView! override func viewDidLoad() { super.viewDidLoad() handler = Handler() tableView.dataSource = handler } } 

处理程序类:

 import UIKit class Handler:NSObject, UITableViewDataSource { func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 10 } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("myCell") cell?.textLabel?.text = "row #\(indexPath.row + 1)" return cell! } }