如何防止访问其他 类 的委托方法?
How to prevent accessing delegate methods for other classes?
为了制作 "more encapsulated" 应用程序,我正在尝试为我的视图控制器指定访问级别 properties/methods。但问题是当尝试 private
一个 datasource/delegate 方法时,我收到一个编译时错误抱怨它。
比如我有两个视图控制器:ViewControllerA
和ViewControllerB
,第一个实现了table视图数据源方法和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' is inaccessible due to 'private' protection level
太合适了!我想阻止其他 class 访问 vcA.privateWork()
。
我的问题是: 简单地说,我想对数据源方法执行相同的操作,所以如果我尝试实现:
private func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 101
}
我遇到编译时错误:
Method 'tableView(_:numberOfRowsInSection:)' must be as accessible as
its enclosing type because it matches a requirement in protocol
'UITableViewDataSource'
有一个修正建议让 private
变成 internal
。它导致以下代码(在第二个视图控制器中):
vcA.tableView(..., numberOfRowsInSection: ...)
要有效,这是不合适的,没有必要让这样的数据源方法可以从其 class 外部访问。
遇到这种情况怎么办?
制作 table 符合 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
}
}
}
您无需担心委托和数据源方法的隐私问题,您仍然可以选择创建另一个 class 来处理您的 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 中,您可以使用此 class 作为您的数据源
class IceCreamListViewController: UITableViewController
{
let dataSource = IceCreamListDataSource()
// MARK: - View lifecycle
override func viewDidLoad()
{
super.viewDidLoad()
tableView.dataSource = dataSource
}
}
希望对您有所帮助
为了制作 "more encapsulated" 应用程序,我正在尝试为我的视图控制器指定访问级别 properties/methods。但问题是当尝试 private
一个 datasource/delegate 方法时,我收到一个编译时错误抱怨它。
比如我有两个视图控制器:ViewControllerA
和ViewControllerB
,第一个实现了table视图数据源方法和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' is inaccessible due to 'private' protection level
太合适了!我想阻止其他 class 访问 vcA.privateWork()
。
我的问题是: 简单地说,我想对数据源方法执行相同的操作,所以如果我尝试实现:
private func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 101
}
我遇到编译时错误:
Method 'tableView(_:numberOfRowsInSection:)' must be as accessible as its enclosing type because it matches a requirement in protocol 'UITableViewDataSource'
有一个修正建议让 private
变成 internal
。它导致以下代码(在第二个视图控制器中):
vcA.tableView(..., numberOfRowsInSection: ...)
要有效,这是不合适的,没有必要让这样的数据源方法可以从其 class 外部访问。
遇到这种情况怎么办?
制作 table 符合 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
}
}
}
您无需担心委托和数据源方法的隐私问题,您仍然可以选择创建另一个 class 来处理您的 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 中,您可以使用此 class 作为您的数据源
class IceCreamListViewController: UITableViewController
{
let dataSource = IceCreamListDataSource()
// MARK: - View lifecycle
override func viewDidLoad()
{
super.viewDidLoad()
tableView.dataSource = dataSource
}
}
希望对您有所帮助