RxSwift/RxCocoa/RxCocoa/iOS/UICollectionView+Rx.swift

130 lines
4.8 KiB
Swift
Raw Normal View History

//
// UICollectionView+Rx.swift
// RxCocoa
//
// Created by Krunoslav Zaher on 4/2/15.
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
//
import Foundation
2015-08-01 16:13:26 +03:00
#if !RX_NO_MODULE
2015-04-10 02:52:51 +03:00
import RxSwift
2015-08-01 16:13:26 +03:00
#endif
import UIKit
2015-07-03 21:57:04 +03:00
extension UICollectionView {
2015-07-03 21:57:04 +03:00
// factories
2015-07-05 12:34:31 +03:00
override func rx_createDelegateProxy() -> RxScrollViewDelegateProxy {
return RxCollectionViewDelegateProxy(parentObject: self)
}
2015-06-29 01:54:05 +03:00
2015-07-05 12:34:31 +03:00
// proxies
public var rx_dataSource: DelegateProxy {
get {
return proxyForObject(self) as RxCollectionViewDataSourceProxy
}
}
2015-07-05 19:40:06 +03:00
// For more detailed explanations, take a look at `DelegateProxyType.swift`
public func rx_setDataSource(dataSource: UICollectionViewDataSource)
-> Disposable {
let proxy: RxCollectionViewDataSourceProxy = proxyForObject(self)
return installDelegate(proxy, delegate: dataSource, retainDelegate: false, onProxyForObject: self)
2015-07-05 19:40:06 +03:00
}
2015-07-03 21:57:04 +03:00
// data source
2015-07-03 21:57:04 +03:00
// Registers reactive data source with collection view.
// Difference between reactive data source and UICollectionViewDataSource is that reactive
// has additional method:
//
// ```
// func collectionView(collectionView: UICollectionView, observedEvent: Event<Element>) -> Void
// ```
//
// If you want to register non reactive data source, please use `rx_setDataSource` method
2015-07-04 14:22:05 +03:00
public func rx_subscribeWithReactiveDataSource<DataSource: protocol<RxCollectionViewDataSourceType, UICollectionViewDataSource>>
2015-07-03 21:57:04 +03:00
(dataSource: DataSource)
-> Observable<DataSource.Element> -> Disposable {
return setProxyDataSourceForObject(self, dataSource: dataSource, retainDataSource: false) { (_: RxCollectionViewDataSourceProxy, event) -> Void in
2015-07-05 19:40:06 +03:00
dataSource.collectionView(self, observedEvent: event)
}
}
2015-07-05 19:40:06 +03:00
2015-07-03 21:57:04 +03:00
// `reloadData` - items subscription methods (it's assumed that there is one section, and it is typed `Void`)
2015-07-03 21:57:04 +03:00
public func rx_subscribeItemsTo<Item>
2015-07-05 19:40:06 +03:00
(cellFactory: (UICollectionView, Int, Item) -> UICollectionViewCell)
2015-07-03 21:57:04 +03:00
-> Observable<[Item]> -> Disposable {
return { source in
let dataSource = RxCollectionViewReactiveArrayDataSource<Item>(cellFactory: cellFactory)
return self.rx_subscribeWithReactiveDataSource(dataSource)(source)
}
2015-07-03 21:57:04 +03:00
}
public func rx_subscribeItemsToWithCellIdentifier<Item, Cell: UICollectionViewCell>
2015-07-05 19:40:06 +03:00
(cellIdentifier: String, configureCell: (Int, Item, Cell) -> Void)
2015-07-03 21:57:04 +03:00
-> Observable<[Item]> -> Disposable {
return { source in
2015-07-05 19:40:06 +03:00
let dataSource = RxCollectionViewReactiveArrayDataSource<Item> { (cv, i, item) in
let indexPath = NSIndexPath(forItem: i, inSection: 0)
2015-07-03 21:57:04 +03:00
let cell = cv.dequeueReusableCellWithReuseIdentifier(cellIdentifier, forIndexPath: indexPath) as! Cell
2015-07-05 19:40:06 +03:00
configureCell(i, item, cell)
2015-07-03 21:57:04 +03:00
return cell
}
2015-07-03 21:57:04 +03:00
return self.rx_subscribeWithReactiveDataSource(dataSource)(source)
2015-05-01 23:04:41 +03:00
}
}
2015-07-03 21:57:04 +03:00
// events
2015-07-05 12:34:31 +03:00
public var rx_itemSelected: Observable<NSIndexPath> {
2015-07-05 19:40:06 +03:00
return rx_delegate.observe("collectionView:didSelectItemAtIndexPath:")
>- map { a in
return a[1] as! NSIndexPath
}
2015-07-03 21:57:04 +03:00
}
// typed events
2015-07-05 12:34:31 +03:00
public func rx_modelSelected<T>() -> Observable<T> {
return rx_itemSelected >- map { indexPath in
let dataSource: RxCollectionViewReactiveArrayDataSource<T> = castOrFatalError(self.rx_dataSource.forwardToDelegate(), message: "This method only works in case one of the `rx_subscribeItemsTo` methods was used.")
2015-07-03 21:57:04 +03:00
return dataSource.modelAtIndex(indexPath.item)!
}
}
2015-07-05 19:40:06 +03:00
}
// deprecated
extension UICollectionView {
@available(*, deprecated=1.7, message="Replaced by `rx_subscribeItemsToWithCellIdentifier`")
2015-07-05 19:40:06 +03:00
public func rx_subscribeItemsWithIdentifierTo<E, Cell where E : AnyObject, Cell : UICollectionViewCell>
(cellIdentifier: String, configureCell: (UICollectionView, NSIndexPath, E, Cell) -> Void)
(source: Observable<[E]>)
-> Disposable {
let l = rx_subscribeItemsToWithCellIdentifier(cellIdentifier) { (i: Int, e: E, cell: Cell) in
return configureCell(self, NSIndexPath(forItem: i, inSection: 0), e, cell)
}
return l(source)
}
@available(*, deprecated=1.7, message="Replaced by `rx_itemSelected`")
2015-07-05 19:40:06 +03:00
public func rx_itemTap() -> Observable<(UICollectionView, Int)> {
return rx_itemSelected
>- map { i in
return (self, i.item)
}
}
@available(*, deprecated=1.7, message="Replaced by `rx_modelSelected`")
2015-07-05 19:40:06 +03:00
public func rx_elementTap<E>() -> Observable<E> {
return rx_modelSelected()
}
}