/OkDataSources

Wrappers for iOS TableView and CollectionView DataSources to simplify its api at a minimum. Also it has a cool PagerView and SlidingTabs!

Primary LanguageSwiftApache License 2.0Apache-2.0

Version License Platform Language

OkDataSources

Wrappers for iOS TableView and CollectionView DataSources to simply its api at a minimum. Also it has a cool PagerView and SlidingTabs! Compatibility with swift 5.0

Setup

Add OkDataSources pod to the podfile

source 'https://github.com/pdecarcer/OkDataSources.git'
pod 'OkDataSources'

Usage

OkDataSources provides several dataSources and delegates to deal with iOS TableViews and CollectionViews

TableViews

class TableViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!
    var dataSource: OkTableViewDataSource<Item, TableViewCell>!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        dataSource = OkTableViewDataSource()
        tableView.dataSource = dataSource
    }
    
}

Look that OkTableViewDataSource<Item, TableViewCell> needs an object and a tableViewCell (which has to conform OkViewCell protocol)

class TableViewCell: UITableViewCell, OkViewCell {
    
    @IBOutlet weak var valueLabel: UILabel!
    
    func configureItem(item: Item) {
        valueLabel.text = item.value
    }
}

In the Storyboard the cell needs to have an identifier like this "\(CLASSNAME)" (For instance: TableViewCell)

TableViewCell - 1 TableViewCell - 2

If you want to receive feedback about items selection, you need to add an OkTableViewDelegate to your ViewController, so onItemClicked block its going to be called every time the user clicks an item.

class TableViewController: UIViewController, OkViewCellDelegate {

    @IBOutlet weak var tableView: UITableView!
    var dataSource: OkTableViewDataSource<Item, TableViewCell>!
    var delegate: OkTableViewDelegate<OkTableViewDataSource<Item, TableViewCell>, TableViewController>!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        dataSource = OkTableViewDataSource()
        delegate = OkTableViewDelegate(dataSource: dataSource,
            onItemClicked: { (item, position) in
            self.showAlertMessage("\(item.value) clicked")
        })
        tableView.dataSource = dataSource
        tableView.delegate = delegate
    }

}

CollectionView

class CollectionViewController: UIViewController {
    
    @IBOutlet weak var collectionView: UICollectionView!
    var dataSource: OkCollectionViewDataSource<Item, CollectionViewCell>!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        dataSource = OkCollectionViewDataSource()
        collectionView.dataSource = dataSource
    }
    
}

Look that OkCollectionViewDataSource<Item, CollectionViewCell> needs an object and a collectionViewCell (which has to conform OkViewCell protocol)

class CollectionViewCell: UICollectionViewCell, OkViewCell {
    
    @IBOutlet weak var valueLabel: UILabel!
    
    func configureItem(item: Item) {
        valueLabel.text = item.value
    }
}

In the Storyboard the cells needs to have an identifier like this "\(CLASSNAME)" (For instance: CollectionViewCell)

CollectionViewCell - 1 CollectionViewCell - 2

If you want to receive feedback about items selection, you need to add an OkCollectionViewDelegate to your ViewController, so onItemClicked block its going to be called every time the user clicks an item.

class CollectionViewController: UIViewController {
    
    @IBOutlet weak var collectionView: UICollectionView!
    var dataSource: OkCollectionViewDataSource<Item, CollectionViewCell>!
    var delegate: OkCollectionViewDelegate<OkCollectionViewDataSource<Item, CollectionViewCell>, CollectionViewController>!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        dataSource = OkCollectionViewDataSource()
        delegate = OkCollectionViewDelegate(dataSource: dataSource,
            onItemClicked: { (item, position) in
                self.showAlertMessage("\(item.value) clicked")
        })
        collectionView.dataSource = dataSource
        collectionView.delegate = delegate
    }
       
}

##Also they have PullToRefresh and Pagination functionalities in their OkDelegates

PullToRefresh

Using tableViews

delegate.setOnPullToRefresh(tableView) { (refreshControl) -> Void in
            print("refreshed")    
            // You need to stop the UIRefreshControl manually when you want to
            refreshControl.endRefreshing()
        }

Using collectionViews

delegate.setOnPullToRefresh(collectionView) { (refreshControl) -> Void in
            print("refreshed")   
             // You need to stop the UIRefreshControl manually when you want to
            refreshControl.endRefreshing()
        }

Pagination

For tableViews and collectionViews

delegate.setOnPagination { (item) -> Void in
           // Ask for more items
        }

##For more Customization

If you need a fully customization of DataSource or Delegate (TableView, CollectionView) you can simply create a class that inherits from them and just override the methods that you need

class ExampleTableViewDataSource: OkTableViewDataSource<Item, TableViewCell> {
    
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let item = itemAtIndexPath(indexPath)

        var cell: TableViewCell!

        // Some condition        
        if indexPath.row == 0 {
            cell = tableView.dequeueReusableCellWithIdentifier("Some Custom Identifier 1", forIndexPath: indexPath) as! TableViewCell
        } else {
            cell = tableView.dequeueReusableCellWithIdentifier("Some Custom Identifier 2", forIndexPath: indexPath) as! TableViewCell
        }
        cell.configureItem(item)
    return cell
}

##RxSwift

There are 2 delegates OkRxTableViewDelegate and OkRxCollectionViewDelegate, use them instead of the regular ones

RxSwift provides extra flavor to the Pagination and PullToRequest functionalities

TableView

delegate = OkRxTableViewDelegate(dataSource: dataSource,
            onItemClicked: { (item, position) in
                self.showAlertMessage("\(item.value) clicked")
        })
        delegate.setOnPullToRefresh(tableView) {
            return Observable.just(self.getMockItems())
        }
        delegate.setOnPagination { (item) -> Observable<[Item]> in
            return Observable.just(self.getMockItems(self.dataSource.items.count))
        }

CollectionView

delegate = OkRxCollectionViewDelegate(dataSource: dataSource,
            onItemClicked: { (item, position) in
                self.showAlertMessage("\(item.value) clicked")
        })
        delegate.setOnPullToRefresh(collectionView) {
            return Observable.just(self.getMockItems())
        }
        delegate.setOnPagination { (item) -> Observable<[Item]> in
            return Observable.just(self.getMockItems(self.dataSource.items.count))
        }   

PagerView

Here is an example PagerViewController

The most convinient way is to use Storyboard. Drag a view to Storyboard and set Class to OkPagerView

Your ViewController will need to implement the OkPagerViewDataSource protocol

public protocol OkPagerViewDataSource {
    
    func viewControllerAtIndex(index: Int) -> UIViewController?
    func numberOfPages() -> Int?
}

And if you want, there is a OkPagerViewDelegate protocol

public protocol OkPagerViewDelegate {
    
    func onPageSelected(viewController: UIViewController, index: Int)
}

SlidingTabs

Here is an example PagerViewController

The most convinient way is to use Storyboard. Drag a view to Storyboard and set Class to OkSlidingTabs

You can customize this attributes through the Storyboard:

  • xPadding: CGFloat
  • xMargin: CGFloat
  • labelTextColor: UIColor
  • labelBgColor: UIColor
  • indicatorColor: UIColor
  • indicatorHeight: CGFloat
  • distributeEvenly: Bool

And If you want to use a different font you'll need to do: slidingTabs.font = newFont

Your ViewController will need to implement the OkSlidingTabsDataSource protocol

public protocol OkSlidingTabsDataSource {
    func numberOfTabs() -> Int
    func titleAtIndex(index: Int) -> String
}

And if you want, there is a OkSlidingTabsDelegate protocol

public protocol OkSlidingTabsDelegate {
    func onTabSelected(index: Int)
}

##Credits This approach is based on https://github.com/Karumi/BothamUI Thanks for the base of this https://github.com/FuckBoilerplate