如何防止访问其他类的委托方法?
Posted
技术标签:
【中文标题】如何防止访问其他类的委托方法?【英文标题】:How to prevent accessing delegate methods for other classes? 【发布时间】:2018-07-23 14:18:24 【问题描述】:为了制作“更多encapsulated”应用程序,我正在尝试为我的视图控制器属性/方法指定访问级别。但问题是当尝试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: ...)
为了有效,这是不恰当的,没有必要让这样的数据源方法可以从其类外部访问。
遇到这种情况该怎么办?
【问题讨论】:
【参考方案1】:您无需担心委托和数据源方法的隐私,您仍然可以选择创建另一个将处理您的 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
希望对你有帮助
【讨论】:
【参考方案2】:制作符合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
【讨论】:
忘记了适配器...另外,如果不需要从文件中使用,您可以将TableViewAdapter
声明为fileprivate
...以上是关于如何防止访问其他类的委托方法?的主要内容,如果未能解决你的问题,请参考以下文章