2016-05-06 3 views
4

Я пытаюсь отделить dataSource и делегат от viewController, чтобы предотвратить недопустимость viewController. Я прочитал несколько постов и обнаружил, что я могу отделить DataSource, как показано ниже, создать класс для представления dataSource:Как отделить dataSource и делегат от класса viewController в Swift?

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) 
} 
+1

Почему не расширение для каждого протокола в том же файл? – vadian

+0

@vadian Как сохранить свойства Если я использую расширение? например, 'var movies = [String]()' Я не буду хранить эти свойства в классе viewController – luiyezheng

+1

OK, свойство для массива источников данных должно быть объявлено в контроллере представления, но это меньшее зло, чем танец для передавать все необходимые ссылки туда и обратно. – vadian

ответ

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) 
} 
+0

Эй @anhut Где я должен называть 'dataSource.selectedItemAtIndex()'? На мой взгляд, класс контроля? – luiyezheng

+1

@luiyezheng Да, где вы определяете dataSource/init экземпляр DataSource – anhtu

+0

обновление для быстрого 4? – Osa

1

Вы не хотите, чтобы соединить ваш источник данных с навигационной логикой, как presentViewController. Вместо этого ваш источник данных может иметь делегат, а источник данных сообщает делегату, что определенное действие было выполнено пользователем. Таким образом, делегат не должен знать о таких деталях, как indexPaths; делегат источника данных может быть viewController, которому принадлежит как collectionView, так и dataSource коллекции.

UIViewController: имеет свойства UICollectionView и свойство YourDataSource. И viewController устанавливает себя как делегат экземпляра YourDataSource. При осуществлении YourDataSource-х collectionViewDidSelectItemAtIndexPath, вы можете получить фильм, который живет в этой indexPath и вызывать делегат с помощью метода, как

func dataSource(dataSource: YourDataSource, didSelectMovie movie: YourMovieClass) 

Это красиво сделать ViewController не знает о том, как был выбран этот фильм, а можете просто создать, настроить и представить новый viewController для этого фильма.

0

Я искал то же самое и использовали ответить на @Unhtu «s , Во время внедрения я придумал немного легче.

Блока В качестве параметра

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) 
    } 
Смежные вопросы