Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Separating Data Source to another class in Swift

Tags:

I'm trying to keep my view controllers clean as described in this article objc.io Issue #1 Lighter View Controllers. I tested this method in Objective-C and it works fine. I have a separate class which implements UITableViewDataSource methods.

#import "TableDataSource.h"  @interface TableDataSource()  @property (nonatomic, strong) NSArray *items; @property (nonatomic, strong) NSString *cellIdentifier;  @end  @implementation TableDataSource  - (id)initWithItems:(NSArray *)items cellIdentifier:(NSString *)cellIdentifier {     self = [super init];     if (self) {         self.items = items;         self.cellIdentifier = cellIdentifier;     }     return self; }  - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {     return self.items.count; }  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifier forIndexPath:indexPath];      cell.textLabel.text = self.items[indexPath.row];      return cell; }  @end 

From the tableview controller, all I have to do is instantiate a instance of this class and set it as the tableview's data source and it works perfectly.

self.dataSource = [[TableDataSource alloc] initWithItems:@[@"One", @"Two", @"Three"] cellIdentifier:@"Cell"]; self.tableView.dataSource = self.dataSource; 

Now I'm trying to do the same in Swift. First here's my code. Its pretty much of a translation of the Objective-C code above.

import Foundation import UIKit  public class TableDataSource: NSObject, UITableViewDataSource {      var items: [AnyObject]     var cellIdentifier: String      init(items: [AnyObject]!, cellIdentifier: String!) {         self.items = items         self.cellIdentifier = cellIdentifier          super.init()     }      public func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {         return items.count     }      public func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {         let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as UITableViewCell          cell.textLabel?.text = items[indexPath.row] as? String          return cell     }  } 

And I call it like this.

let dataSource = TableDataSource(items: ["One", "Two", "Three"], cellIdentifier: "Cell") tableView.dataSource = dataSource 

But the app crashes with the following error.

-[NSConcreteNotification tableView:numberOfRowsInSection:]: unrecognized selector sent to instance

I checked the init method of TableDataSource and the items and the cell identifier gets passed fine. I had to declare the UITableViewDataSource methods public and remove the override keyword otherwise it would give compile time errors.

I'm clueless on what's going wrong here. Can anyone please help me out?

Thank you.

like image 992
Isuru Avatar asked Sep 11 '14 13:09

Isuru


1 Answers

Create a property for data source and use it with your tableview.

class ViewController: UIViewController {    @IBOutlet weak var tableView: UITableView!   var dataSource:TableDataSource!    override func viewDidLoad() {     super.viewDidLoad()      dataSource = TableDataSource(items: ["One", "Two", "Three"], cellIdentifier: "Cell")     tableView.dataSource = dataSource    } } 
like image 70
ayalcinkaya Avatar answered Sep 19 '22 14:09

ayalcinkaya