For the purpose of making a "more encapsulated" app, I am trying to specify the access levels for my view controllers properties/methods. But the issue is when trying to private
a datasource/delegate method, I am getting a compile-time error complaining about it.
For instance, I have two view controllers: ViewControllerA
and ViewControllerB
, the first one implements the table view datasource method and privateWork()
private method, as follows:
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)
}
}
And the second view controller has an instance of ViewControllerA
-in a method called setupViewControllerA()
- as follows:
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()
}
}
When implementing vcA.privateWork()
it gives a compile-time error:
'privateWork' is inaccessible due to 'private' protection level
which is so appropriate! I want to prevent the accessing of vcA.privateWork()
for other classes.
My issue is: simply, I want to do the same behavior for the datasource methods, so if I tried to implement:
private func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 101
}
I getting a compile time error:
Method 'tableView(_:numberOfRowsInSection:)' must be as accessible as its enclosing type because it matches a requirement in protocol 'UITableViewDataSource'
with a fix suggestion to let private
to be internal
. It leads to let the following code (in the second view controller):
vcA.tableView(..., numberOfRowsInSection: ...)
to be valid, which is inappropriate, there is no need to let such a datasource method to be accessible from outside of its class.
What should I do for such a case?
Make table view adapter that conforms to UITableViewDataSource
and UITableViewDelegate
and add it as private property to your view controller:
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
}
}
}