为什么我们需要将委托设置为自己?为什么它不被编译器默认?

时间:2016-12-21 20:15:00

标签: swift uitableview delegates

认为我完全理解授权的概念,我的问题是当我们这样做时:

class someViewController : UIViewController, UITableViewDelegate{

}

是否永远可能我们不希望将tableView.delegate设置为self

如果没有任何机会,为什么Xcode迫使我们在这里做一些额外的工作?

如果tableView.delegate有可能设置为self以外的其他内容......那么这是什么?你能举一些例子吗?

3 个答案:

答案 0 :(得分:4)

在所需的ViewController中提到tableView.delegate = selftableView.dataSource = self时,这意味着ViewController会说"我负责实现这些委托/数据源方法",意味着这个ViewController(self)正在处理提供所需的方法,让tableView知道它应该是什么样子/行为。

参考您的问题:

  

我们是否有可能不想设置   tableView.delegate to self?

实际上它是可能的,但这导致让tableView显示为一个空的tableView(其中没有行),因为没有人告诉它应该如何看起来/表现。

  

如果tableView.delegate有可能被设置为其他东西   比自己......那是什么?你能举一些例子吗?

是的,你可以,tableView.dataSource / delegate不必分配给包含这个tableView的同一个Viewcontroller(但我发现它更具可读性和可理解性)。

例如:

在下面的代码片段中,我将tableView的dataSource分配给另一个 .swift 文件上的另一个独立的类(甚至不是UIViewController),它完全正常工作:

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!
    }
}

输出正常工作。

答案 1 :(得分:2)

  

我们是否有可能不想设置   tableView.delegate to self

是的,如果你要在它自己的类中实现数据源和委托。

  

为什么Xcode迫使我们在这里做一些额外的工作?

尽可能让我们的架构自由。

使用单独的数据源和委托类的示例。

override func loadView() {
    // this will create default blank view and set it to the 'view' property
    super.loadView()

    let userProfileView = UserProfileView()
    view.addSubview(userProfileView)

    // pin userProfileView left and right edge to superview's left and right edges 
    // its top to view controller's topLayoutGuide
    // and its bottom to view controller's bottomLayoutGuide
}

如果您允许视图控制器保存委托和数据源的不同实现,那么这允许更高的可重用性并且有利于组合而不是继承。

您处理较小的类,并且更容易测试和维护。

甚至可以设计完整的应用程序,不需要任何视图控制器子类。

数据源/委托设计可以随心所欲。

作为一个例子,我想向您展示我的一个新项目:TaCoPopulator。它是一个框架,通过将其拆分为不同的任务来透明地填充表视图和集合视图,以遵循SOLID原则:

class TableViewDatasource: NSObject, UITableViewDataSource {
    // implement datasource
}

class TableViewDelegate : NSObject, UITableViewDelegate {
    // implement delegate
}

class ViewController: UIViewController {

     IBOutlet weak var tableView: UITableView! {
         didSet {
              tableView.dataSource = tableViewDatasource
              tableView.delegate = tableViewDelegate
         }
     }

     let tableViewDatasource = TableViewDatasource()
     let tableViewDelegate = TableViewDelegate()

}
import UIKit

class CollectionViewController: UIViewController {

    @IBOutlet weak var collectionView: UICollectionView!
    private var datasource: ViewControllerDataSource<UICollectionView>?

    override func viewDidLoad() {
        super.viewDidLoad()
        self.datasource = ViewControllerDataSource(with: collectionView)
    }
}
import UIKit

class TableViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!
    private var datasource: ViewControllerDataSource<UITableView>?

    override func viewDidLoad() {
        super.viewDidLoad()
        self.datasource = ViewControllerDataSource(with: tableView)
    }
}
import TaCoPopulator


class IntDataProvider: SectionDataProvider<Int> {

    override init(reuseIdentifer: @escaping (Int, IndexPath) -> String) {
        super.init(reuseIdentifer: reuseIdentifer)
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2) {
            self.provideElements([1,2,3,4,5,6,7,8,9])
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2) {
                self.provideElements(self.elements() + [10, 11, 12, 13, 14, 15])
            }
        }
    }
}

答案 2 :(得分:1)

  

我们是否有可能不想将tableView.delegate设置为self?

什么是tableView.delegate?您的班级someViewController不是UITableViewController的子类(并且没有tableView属性)。它甚至不知道你处理表视图。

您的类型声明符合UITableViewDelegate的事实并没有明确说明它应该设置在哪个实际的表视图实例上。

  

如果tableView.delegate有可能被设置为self以外的东西......那么这是什么?

通常,将功能分成多种类型以降低视图控制器的复杂性是明智的。您的someViewController 可能具有viewModel属性,可处理有关表格视图的所有内容。

相关问题