如何从Swift中的viewController类中分离dataSource和delegate?

时间:2016-05-06 08:55:04

标签: ios swift

我试图从viewController中分离dataSource和delegate,以防止viewController变得混乱。我阅读了一些帖子,发现我可以像下面那样分开dataSource,创建一个代表dataSource的类:

import UIKit

class DataSource: NSObject, UITableViewDataSource, UITableViewDelegate {

    var movies = [String]()

    //MARK: - UITableViewDataSource
    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return movies.count
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCellWithIdentifier("cellIdentifier", forIndexPath: indexPath) as UITableViewCell


        cell.textLabel?.text =  movies[indexPath.row]

        return cell
    }

}

我的问题是:如果我想在viewController课程中使用属性或调用DataSource类的方法,我该怎么办?例如,我想在用户选择单元格时调用presentViewController

func tableView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {

    //do something here

    presentViewController(viewController!, animated: true, completion: nil)
}

3 个答案:

答案 0 :(得分:6)

您可以处理选定的回调:

class DataSource: NSObject, UITableViewDataSource, UITableViewDelegate {

        var movies = [String]()
        private var selectedCallback = ((NSIndexPath)->Void)?

        func selectedItemAtIndex(callback:(NSIndexPath) -> Void) {
            selectedCallback = callback
        }
}

回调:

func tableView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {

    //do something here

    if let callback = selectedCallback {
       callback(indexPath)
    }
}

使用:

dataSource.selectedItemAtIndex() {
  [weak self] indexPath in
  // do something ...
  // presentViewController(viewController!, animated: true, completion: nil)
}

答案 1 :(得分:1)

您不希望将数据源与presentViewController等导航逻辑耦合。相反,您的数据源可以有一个委托,数据源将告诉委托用户执行了某个操作。这样,委托不需要知道像indexPaths这样的细节;数据源的委托可以是拥有collectionView的collectionView和dataSource的viewController。

UIViewController:具有属性UICollectionView和属性YourDataSource。 viewController将自己设置为YourDataSource实例的委托。在YourDataSource的collectionViewDidSelectItemAtIndexPath的实现中,您可以检索位于该indexPath的影片,并使用类似

的方法调用委托。
func  dataSource(dataSource: YourDataSource, didSelectMovie movie: YourMovieClass)

这将很好地使viewController不知道如何选择这部电影,并且可以为这部电影创建,设置和呈现一个新的viewController。

答案 2 :(得分:0)

我正在搜索同样的东西并使用了@Unhtu的答案。在实施的过程中,我提出了一些更容易的事情。

阻止作为参数

 class DataSource: NSObject, UITableViewDataSource, UITableViewDelegate 
{     
    private var selectedCallback : ((NSIndexPath)->Void)? // declaring a parameter

    func tableView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {

       //Accessing the parameter
        if let callback = selectedCallback {
           callback(indexPath)
        }
    }

将参数值分配到ViewController

var dataSource = DataSource()    
 // Assigning the value to the parameter 
 dataSource. selectedCallback = {
           indexPath in
          // do something ...
           presentViewController(viewController!, animated: true, completion: nil)
    }