为了制作一个"更多encapsulated" app,我正在尝试为视图控制器属性/方法指定访问级别。但问题是在尝试private
数据源/委托方法时,我收到了一个抱怨它的编译时错误。
例如,我有两个视图控制器:ViewControllerA
和ViewControllerB
,第一个实现表视图数据源方法和privateWork()
私有方法,如下所示:
class ViewControllerA: UIViewController, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 101
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell")!
return cell
}
private func privateWork() {
print(#function)
}
}
第二个视图控制器的ViewControllerA
实例 - 名为setupViewControllerA()
的方法 - 如下所示:
class ViewControllerB: UIViewController {
func setupViewControllerA() {
// in real case, you should get it from its stroyborad,
// this is only for the purpose of demonstrating the issue...
let vcA = ViewControllerA()
vcA.privateWork()
}
}
实现vcA.privateWork()
时会出现编译时错误:
' privateWork'因私人'而无法访问保护水平
这是非常合适的!我想阻止vcA.privateWork()
访问其他类。
我的问题是:简单地说,我想对数据源方法执行相同的操作,所以如果我尝试实现:
private func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 101
}
我收到编译时错误:
方法' tableView(_:numberOfRowsInSection:)'必须像 它的封闭类型,因为它符合协议中的要求 ' UITableViewDataSource'
提供修正建议,让private
成为internal
。它导致让以下代码(在第二个视图控制器中):
vcA.tableView(..., numberOfRowsInSection: ...)
是有效的,这是不合适的,没有必要让这样的数据源方法可以从它的类外部访问。
我应该为这种情况做些什么?
答案 0 :(得分:2)
您无需担心委托人的隐私权。数据源方法仍然可以选择创建另一个将处理tableview数据源内容的类
例如
class IceCreamListDataSource: NSObject, UITableViewDataSource
{
let dataStore = IceCreamStore()
// MARK: - Table view data source
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return dataStore.allFlavors().count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let flavor = dataStore.allFlavors()[indexPath.row]
let cell = tableView.dequeueReusableCellWithIdentifier("IceCreamListCell", forIndexPath: indexPath)
cell.textLabel?.text = flavor
return cell
}
}
现在在ViewController
或UITableViewController
课程中,您可以将此课程用作数据源
class IceCreamListViewController: UITableViewController
{
let dataSource = IceCreamListDataSource()
// MARK: - View lifecycle
override func viewDidLoad()
{
super.viewDidLoad()
tableView.dataSource = dataSource
}
}
希望它有用
答案 1 :(得分:1)
使表视图适配器符合UITableViewDataSource
和UITableViewDelegate
,并将其作为私有属性添加到视图控制器:
final class TableViewAdapter: NSObject, UITableViewDataSource, UITableViewDelegate {
// Implementation of protocol methods
}
class ViewControllerA: UIViewController {
private let adapter = TableViewAdapter()
@IBOutlet private var tableView: UITableView! {
didSet {
tableView.delegate = adapter
tableView.dataSource = adapter
}
}
}