Improves deprecation messages for table and collection views. #841
This commit is contained in:
parent
e1f72cb566
commit
7208a8d1cc
|
|
@ -20,5 +20,20 @@ public protocol SectionedViewDataSourceType {
|
||||||
- parameter indexPath: Model index path
|
- parameter indexPath: Model index path
|
||||||
- returns: Model at index path.
|
- returns: Model at index path.
|
||||||
*/
|
*/
|
||||||
func modelAtIndexPath(_ indexPath: IndexPath) throws -> Any
|
func model(_ indexPath: IndexPath) throws -> Any
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SectionedViewDataSourceType {
|
||||||
|
/**
|
||||||
|
Returns model at index path.
|
||||||
|
|
||||||
|
In case data source doesn't contain any sections when this method is being called, `RxCocoaError.ItemsNotYetBound(object: self)` is thrown.
|
||||||
|
|
||||||
|
- parameter indexPath: Model index path
|
||||||
|
- returns: Model at index path.
|
||||||
|
*/
|
||||||
|
@available(*, deprecated, renamed: "model(_:)")
|
||||||
|
func model(_ indexPath: IndexPath) throws -> Any {
|
||||||
|
return try self.model(indexPath)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ class RxCollectionViewReactiveArrayDataSource<Element>
|
||||||
return itemModels?[index]
|
return itemModels?[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
func modelAtIndexPath(_ indexPath: IndexPath) throws -> Any {
|
func model(_ indexPath: IndexPath) throws -> Any {
|
||||||
precondition(indexPath.section == 0)
|
precondition(indexPath.section == 0)
|
||||||
guard let item = itemModels?[indexPath.item] else {
|
guard let item = itemModels?[indexPath.item] else {
|
||||||
throw RxCocoaError.itemsNotYetBound(object: self)
|
throw RxCocoaError.itemsNotYetBound(object: self)
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ class RxTableViewReactiveArrayDataSource<Element>
|
||||||
return itemModels?[index]
|
return itemModels?[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
func modelAtIndexPath(_ indexPath: IndexPath) throws -> Any {
|
func model(_ indexPath: IndexPath) throws -> Any {
|
||||||
precondition(indexPath.section == 0)
|
precondition(indexPath.section == 0)
|
||||||
guard let item = itemModels?[indexPath.item] else {
|
guard let item = itemModels?[indexPath.item] else {
|
||||||
throw RxCocoaError.itemsNotYetBound(object: self)
|
throw RxCocoaError.itemsNotYetBound(object: self)
|
||||||
|
|
|
||||||
|
|
@ -17,43 +17,7 @@ import UIKit
|
||||||
// Items
|
// Items
|
||||||
|
|
||||||
extension Reactive where Base: UICollectionView {
|
extension Reactive where Base: UICollectionView {
|
||||||
|
|
||||||
/**
|
|
||||||
Binds sequences of elements to collection view items.
|
|
||||||
|
|
||||||
- parameter source: Observable sequence of items.
|
|
||||||
- parameter cellFactory: Transform between sequence elements and view cells.
|
|
||||||
- returns: Disposable object that can be used to unbind.
|
|
||||||
|
|
||||||
Example
|
|
||||||
|
|
||||||
let items = Observable.just([
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3
|
|
||||||
])
|
|
||||||
|
|
||||||
items
|
|
||||||
.bindTo(collectionView.rx.itemsWithCellFactory) { (collectionView, row, element) in
|
|
||||||
let indexPath = IndexPath(forItem: row, inSection: 0)
|
|
||||||
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! NumberCell
|
|
||||||
cell.value?.text = "\(element) @ \(row)"
|
|
||||||
return cell
|
|
||||||
}
|
|
||||||
.addDisposableTo(disposeBag)
|
|
||||||
*/
|
|
||||||
@available(*, deprecated, renamed: "items(source:cellFactory:)")
|
|
||||||
public func rx_itemsWithCellFactory<S: Sequence, O: ObservableType>
|
|
||||||
(_ source: O)
|
|
||||||
-> (_ cellFactory: @escaping (UICollectionView, Int, S.Iterator.Element) -> UICollectionViewCell)
|
|
||||||
-> Disposable where O.E == S {
|
|
||||||
return { cellFactory in
|
|
||||||
let dataSource = RxCollectionViewReactiveArrayDataSourceSequenceWrapper<S>(cellFactory: cellFactory)
|
|
||||||
return self.items(dataSource: dataSource)(source)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Binds sequences of elements to collection view items.
|
Binds sequences of elements to collection view items.
|
||||||
|
|
||||||
|
|
@ -79,7 +43,7 @@ extension Reactive where Base: UICollectionView {
|
||||||
.addDisposableTo(disposeBag)
|
.addDisposableTo(disposeBag)
|
||||||
*/
|
*/
|
||||||
public func items<S: Sequence, O: ObservableType>
|
public func items<S: Sequence, O: ObservableType>
|
||||||
(source: O)
|
(_ source: O)
|
||||||
-> (_ cellFactory: @escaping (UICollectionView, Int, S.Iterator.Element) -> UICollectionViewCell)
|
-> (_ cellFactory: @escaping (UICollectionView, Int, S.Iterator.Element) -> UICollectionViewCell)
|
||||||
-> Disposable where O.E == S {
|
-> Disposable where O.E == S {
|
||||||
return { cellFactory in
|
return { cellFactory in
|
||||||
|
|
@ -92,49 +56,6 @@ extension Reactive where Base: UICollectionView {
|
||||||
/**
|
/**
|
||||||
Binds sequences of elements to collection view items.
|
Binds sequences of elements to collection view items.
|
||||||
|
|
||||||
- parameter cellIdentifier: Identifier used to dequeue cells.
|
|
||||||
- parameter source: Observable sequence of items.
|
|
||||||
- parameter configureCell: Transform between sequence elements and view cells.
|
|
||||||
- parameter cellType: Type of table view cell.
|
|
||||||
- returns: Disposable object that can be used to unbind.
|
|
||||||
|
|
||||||
Example
|
|
||||||
|
|
||||||
let items = Observable.just([
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3
|
|
||||||
])
|
|
||||||
|
|
||||||
items
|
|
||||||
.bindTo(collectionView.rx.itemsWithCellIdentifier("Cell", cellType: NumberCell.self)) { (row, element, cell) in
|
|
||||||
cell.value?.text = "\(element) @ \(row)"
|
|
||||||
}
|
|
||||||
.addDisposableTo(disposeBag)
|
|
||||||
*/
|
|
||||||
@available(*, deprecated, renamed: "items(cellIdentifier:cellType:source:configureCell:)")
|
|
||||||
public func rx_itemsWithCellIdentifier<S: Sequence, Cell: UICollectionViewCell, O : ObservableType>
|
|
||||||
(_ cellIdentifier: String, cellType: Cell.Type = Cell.self)
|
|
||||||
-> (_ source: O)
|
|
||||||
-> (_ configureCell: @escaping (Int, S.Iterator.Element, Cell) -> Void)
|
|
||||||
-> Disposable where O.E == S {
|
|
||||||
return { source in
|
|
||||||
return { configureCell in
|
|
||||||
let dataSource = RxCollectionViewReactiveArrayDataSourceSequenceWrapper<S> { (cv, i, item) in
|
|
||||||
let indexPath = IndexPath(item: i, section: 0)
|
|
||||||
let cell = cv.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! Cell
|
|
||||||
configureCell(i, item, cell)
|
|
||||||
return cell
|
|
||||||
}
|
|
||||||
|
|
||||||
return self.items(dataSource: dataSource)(source)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Binds sequences of elements to collection view items.
|
|
||||||
|
|
||||||
- parameter cellIdentifier: Identifier used to dequeue cells.
|
- parameter cellIdentifier: Identifier used to dequeue cells.
|
||||||
- parameter source: Observable sequence of items.
|
- parameter source: Observable sequence of items.
|
||||||
- parameter configureCell: Transform between sequence elements and view cells.
|
- parameter configureCell: Transform between sequence elements and view cells.
|
||||||
|
|
@ -175,63 +96,6 @@ extension Reactive where Base: UICollectionView {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Binds sequences of elements to collection view items using a custom reactive data used to perform the transformation.
|
|
||||||
|
|
||||||
- parameter dataSource: Data source used to transform elements to view cells.
|
|
||||||
- parameter source: Observable sequence of items.
|
|
||||||
- returns: Disposable object that can be used to unbind.
|
|
||||||
|
|
||||||
Example
|
|
||||||
|
|
||||||
let dataSource = RxCollectionViewSectionedReloadDataSource<SectionModel<String, Double>>()
|
|
||||||
|
|
||||||
let items = Observable.just([
|
|
||||||
SectionModel(model: "First section", items: [
|
|
||||||
1.0,
|
|
||||||
2.0,
|
|
||||||
3.0
|
|
||||||
]),
|
|
||||||
SectionModel(model: "Second section", items: [
|
|
||||||
1.0,
|
|
||||||
2.0,
|
|
||||||
3.0
|
|
||||||
]),
|
|
||||||
SectionModel(model: "Third section", items: [
|
|
||||||
1.0,
|
|
||||||
2.0,
|
|
||||||
3.0
|
|
||||||
])
|
|
||||||
])
|
|
||||||
|
|
||||||
dataSource.configureCell = { (dataSource, cv, indexPath, element) in
|
|
||||||
let cell = cv.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! NumberCell
|
|
||||||
cell.value?.text = "\(element) @ row \(indexPath.row)"
|
|
||||||
return cell
|
|
||||||
}
|
|
||||||
|
|
||||||
items
|
|
||||||
.bindTo(collectionView.rx.itemsWithDataSource(dataSource))
|
|
||||||
.addDisposableTo(disposeBag)
|
|
||||||
*/
|
|
||||||
@available(*, deprecated, renamed: "items(dataSource:source:)")
|
|
||||||
public func rx_itemsWithDataSource<
|
|
||||||
DataSource: RxCollectionViewDataSourceType & UICollectionViewDataSource,
|
|
||||||
O: ObservableType>
|
|
||||||
(_ dataSource: DataSource)
|
|
||||||
-> (_ source: O)
|
|
||||||
-> Disposable where DataSource.Element == O.E
|
|
||||||
{
|
|
||||||
return { source in
|
|
||||||
return source.subscribeProxyDataSource(ofObject: self.base, dataSource: dataSource, retainDataSource: true) { [weak collectionView = self.base] (_: RxCollectionViewDataSourceProxy, event) -> Void in
|
|
||||||
guard let collectionView = collectionView else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
dataSource.collectionView(collectionView, observedEvent: event)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Binds sequences of elements to collection view items using a custom reactive data used to perform the transformation.
|
Binds sequences of elements to collection view items using a custom reactive data used to perform the transformation.
|
||||||
|
|
||||||
|
|
@ -283,7 +147,7 @@ extension Reactive where Base: UICollectionView {
|
||||||
// data source is being bound.
|
// data source is being bound.
|
||||||
// This is needed because theoretically the data source subscription itself might
|
// This is needed because theoretically the data source subscription itself might
|
||||||
// call `self.rx_delegate`. If that happens, it might cause weird side effects since
|
// call `self.rx_delegate`. If that happens, it might cause weird side effects since
|
||||||
// setting data source will set delegate, and UITableView might get into a weird state.
|
// setting data source will set delegate, and UICollectionView might get into a weird state.
|
||||||
// Therefore it's better to set delegate proxy first, just to be sure.
|
// Therefore it's better to set delegate proxy first, just to be sure.
|
||||||
_ = self.delegate
|
_ = self.delegate
|
||||||
// Strong reference is needed because data source is in use until result subscription is disposed
|
// Strong reference is needed because data source is in use until result subscription is disposed
|
||||||
|
|
@ -385,7 +249,7 @@ extension Reactive where Base: UICollectionView {
|
||||||
return Observable.empty()
|
return Observable.empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
return Observable.just(try view.rx.modelAtIndexPath(indexPath))
|
return Observable.just(try view.rx.model(indexPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
return ControlEvent(events: source)
|
return ControlEvent(events: source)
|
||||||
|
|
@ -408,7 +272,7 @@ extension Reactive where Base: UICollectionView {
|
||||||
return Observable.empty()
|
return Observable.empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
return Observable.just(try view.rx.modelAtIndexPath(indexPath))
|
return Observable.just(try view.rx.model(indexPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
return ControlEvent(events: source)
|
return ControlEvent(events: source)
|
||||||
|
|
@ -417,10 +281,10 @@ extension Reactive where Base: UICollectionView {
|
||||||
/**
|
/**
|
||||||
Syncronous helper method for retrieving a model at indexPath through a reactive data source
|
Syncronous helper method for retrieving a model at indexPath through a reactive data source
|
||||||
*/
|
*/
|
||||||
public func modelAtIndexPath<T>(_ indexPath: IndexPath) throws -> T {
|
public func model<T>(_ indexPath: IndexPath) throws -> T {
|
||||||
let dataSource: SectionedViewDataSourceType = castOrFatalError(self.dataSource.forwardToDelegate(), message: "This method only works in case one of the `rx.itemsWith*` methods was used.")
|
let dataSource: SectionedViewDataSourceType = castOrFatalError(self.dataSource.forwardToDelegate(), message: "This method only works in case one of the `rx.itemsWith*` methods was used.")
|
||||||
|
|
||||||
let element = try dataSource.modelAtIndexPath(indexPath)
|
let element = try dataSource.model(indexPath)
|
||||||
|
|
||||||
return element as! T
|
return element as! T
|
||||||
}
|
}
|
||||||
|
|
@ -447,3 +311,137 @@ extension Reactive where Base: UICollectionView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extension UICollectionView {
|
||||||
|
|
||||||
|
/**
|
||||||
|
Binds sequences of elements to collection view items.
|
||||||
|
|
||||||
|
- parameter cellIdentifier: Identifier used to dequeue cells.
|
||||||
|
- parameter source: Observable sequence of items.
|
||||||
|
- parameter configureCell: Transform between sequence elements and view cells.
|
||||||
|
- parameter cellType: Type of table view cell.
|
||||||
|
- returns: Disposable object that can be used to unbind.
|
||||||
|
|
||||||
|
Example
|
||||||
|
|
||||||
|
let items = Observable.just([
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3
|
||||||
|
])
|
||||||
|
|
||||||
|
items
|
||||||
|
.bindTo(collectionView.rx.items(cellIdentifier: "Cell", cellType: NumberCell.self)) { (row, element, cell) in
|
||||||
|
cell.value?.text = "\(element) @ \(row)"
|
||||||
|
}
|
||||||
|
.addDisposableTo(disposeBag)
|
||||||
|
*/
|
||||||
|
@available(*, deprecated, renamed: "items(cellIdentifier:cellType:_:_:)")
|
||||||
|
public func rx_itemsWithCellIdentifier<S: Sequence, Cell: UICollectionViewCell, O : ObservableType>
|
||||||
|
(_ cellIdentifier: String, cellType: Cell.Type = Cell.self)
|
||||||
|
-> (_ source: O)
|
||||||
|
-> (_ configureCell: @escaping (Int, S.Iterator.Element, Cell) -> Void)
|
||||||
|
-> Disposable where O.E == S {
|
||||||
|
return { source in
|
||||||
|
return { configureCell in
|
||||||
|
return self.rx.items(cellIdentifier: cellIdentifier, cellType: cellType)(source)(configureCell)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Binds sequences of elements to collection view items.
|
||||||
|
|
||||||
|
- parameter source: Observable sequence of items.
|
||||||
|
- parameter cellFactory: Transform between sequence elements and view cells.
|
||||||
|
- returns: Disposable object that can be used to unbind.
|
||||||
|
|
||||||
|
Example
|
||||||
|
|
||||||
|
let items = Observable.just([
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3
|
||||||
|
])
|
||||||
|
|
||||||
|
items
|
||||||
|
.bindTo(collectionView.rx.items) { (collectionView, row, element) in
|
||||||
|
let indexPath = IndexPath(forItem: row, inSection: 0)
|
||||||
|
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! NumberCell
|
||||||
|
cell.value?.text = "\(element) @ \(row)"
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
.addDisposableTo(disposeBag)
|
||||||
|
*/
|
||||||
|
@available(*, deprecated, renamed: "items(_:_:)")
|
||||||
|
public func rx_itemsWithCellFactory<S: Sequence, O: ObservableType>
|
||||||
|
(_ source: O)
|
||||||
|
-> (_ cellFactory: @escaping (UICollectionView, Int, S.Iterator.Element) -> UICollectionViewCell)
|
||||||
|
-> Disposable where O.E == S {
|
||||||
|
return { cellFactory in
|
||||||
|
return self.rx.items(source)(cellFactory)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Binds sequences of elements to collection view items using a custom reactive data used to perform the transformation.
|
||||||
|
|
||||||
|
- parameter dataSource: Data source used to transform elements to view cells.
|
||||||
|
- parameter source: Observable sequence of items.
|
||||||
|
- returns: Disposable object that can be used to unbind.
|
||||||
|
|
||||||
|
Example
|
||||||
|
|
||||||
|
let dataSource = RxCollectionViewSectionedReloadDataSource<SectionModel<String, Double>>()
|
||||||
|
|
||||||
|
let items = Observable.just([
|
||||||
|
SectionModel(model: "First section", items: [
|
||||||
|
1.0,
|
||||||
|
2.0,
|
||||||
|
3.0
|
||||||
|
]),
|
||||||
|
SectionModel(model: "Second section", items: [
|
||||||
|
1.0,
|
||||||
|
2.0,
|
||||||
|
3.0
|
||||||
|
]),
|
||||||
|
SectionModel(model: "Third section", items: [
|
||||||
|
1.0,
|
||||||
|
2.0,
|
||||||
|
3.0
|
||||||
|
])
|
||||||
|
])
|
||||||
|
|
||||||
|
dataSource.configureCell = { (dataSource, cv, indexPath, element) in
|
||||||
|
let cell = cv.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! NumberCell
|
||||||
|
cell.value?.text = "\(element) @ row \(indexPath.row)"
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
|
||||||
|
items
|
||||||
|
.bindTo(collectionView.rx.items(dataSource: dataSource))
|
||||||
|
.addDisposableTo(disposeBag)
|
||||||
|
*/
|
||||||
|
@available(*, deprecated, renamed: "items(dataSource:_:)")
|
||||||
|
public func rx_itemsWithDataSource<
|
||||||
|
DataSource: RxCollectionViewDataSourceType & UICollectionViewDataSource,
|
||||||
|
O: ObservableType>
|
||||||
|
(_ dataSource: DataSource)
|
||||||
|
-> (_ source: O)
|
||||||
|
-> Disposable where DataSource.Element == O.E
|
||||||
|
{
|
||||||
|
return { source in
|
||||||
|
return self.rx.items(dataSource: dataSource)(source)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Syncronous helper method for retrieving a model at indexPath through a reactive data source
|
||||||
|
*/
|
||||||
|
@available(*, deprecated, renamed: "rx.model(_:)")
|
||||||
|
public func model<T>(_ indexPath: IndexPath) throws -> T {
|
||||||
|
return try self.rx.model(indexPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,43 +17,6 @@ import UIKit
|
||||||
// Items
|
// Items
|
||||||
|
|
||||||
extension Reactive where Base: UITableView {
|
extension Reactive where Base: UITableView {
|
||||||
|
|
||||||
/**
|
|
||||||
Binds sequences of elements to table view rows.
|
|
||||||
|
|
||||||
- parameter source: Observable sequence of items.
|
|
||||||
- parameter cellFactory: Transform between sequence elements and view cells.
|
|
||||||
- returns: Disposable object that can be used to unbind.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
let items = Observable.just([
|
|
||||||
"First Item",
|
|
||||||
"Second Item",
|
|
||||||
"Third Item"
|
|
||||||
])
|
|
||||||
|
|
||||||
items
|
|
||||||
.bindTo(tableView.rx.itemsWithCellFactory) { (tableView, row, element) in
|
|
||||||
let cell = tableView.dequeueReusableCellWithIdentifier("Cell")!
|
|
||||||
cell.textLabel?.text = "\(element) @ row \(row)"
|
|
||||||
return cell
|
|
||||||
}
|
|
||||||
.addDisposableTo(disposeBag)
|
|
||||||
|
|
||||||
*/
|
|
||||||
@available(*, deprecated, renamed: "items(source:cellFactory:)")
|
|
||||||
public func rx_itemsWithCellFactory<S: Sequence, O: ObservableType>
|
|
||||||
(_ source: O)
|
|
||||||
-> (_ cellFactory: @escaping (UITableView, Int, S.Iterator.Element) -> UITableViewCell)
|
|
||||||
-> Disposable
|
|
||||||
where O.E == S {
|
|
||||||
return { cellFactory in
|
|
||||||
let dataSource = RxTableViewReactiveArrayDataSourceSequenceWrapper<S>(cellFactory: cellFactory)
|
|
||||||
|
|
||||||
return self.items(dataSource: dataSource)(source)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Binds sequences of elements to table view rows.
|
Binds sequences of elements to table view rows.
|
||||||
|
|
@ -71,7 +34,7 @@ extension Reactive where Base: UITableView {
|
||||||
])
|
])
|
||||||
|
|
||||||
items
|
items
|
||||||
.bindTo(tableView.items) { (tableView, row, element) in
|
.bindTo(tableView.rx.items) { (tableView, row, element) in
|
||||||
let cell = tableView.dequeueReusableCellWithIdentifier("Cell")!
|
let cell = tableView.dequeueReusableCellWithIdentifier("Cell")!
|
||||||
cell.textLabel?.text = "\(element) @ row \(row)"
|
cell.textLabel?.text = "\(element) @ row \(row)"
|
||||||
return cell
|
return cell
|
||||||
|
|
@ -93,49 +56,6 @@ extension Reactive where Base: UITableView {
|
||||||
/**
|
/**
|
||||||
Binds sequences of elements to table view rows.
|
Binds sequences of elements to table view rows.
|
||||||
|
|
||||||
- parameter cellIdentifier: Identifier used to dequeue cells.
|
|
||||||
- parameter source: Observable sequence of items.
|
|
||||||
- parameter configureCell: Transform between sequence elements and view cells.
|
|
||||||
- parameter cellType: Type of table view cell.
|
|
||||||
- returns: Disposable object that can be used to unbind.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
let items = Observable.just([
|
|
||||||
"First Item",
|
|
||||||
"Second Item",
|
|
||||||
"Third Item"
|
|
||||||
])
|
|
||||||
|
|
||||||
items
|
|
||||||
.bindTo(tableView.rx.itemsWithCellIdentifier("Cell", cellType: UITableViewCell.self)) { (row, element, cell) in
|
|
||||||
cell.textLabel?.text = "\(element) @ row \(row)"
|
|
||||||
}
|
|
||||||
.addDisposableTo(disposeBag)
|
|
||||||
*/
|
|
||||||
@available(*, deprecated, renamed: "items(cellIdentifier:cellType:source:configureCell:)")
|
|
||||||
public func rx_itemsWithCellIdentifier<S: Sequence, Cell: UITableViewCell, O : ObservableType>
|
|
||||||
(_ cellIdentifier: String, cellType: Cell.Type = Cell.self)
|
|
||||||
-> (_ source: O)
|
|
||||||
-> (_ configureCell: @escaping (Int, S.Iterator.Element, Cell) -> Void)
|
|
||||||
-> Disposable
|
|
||||||
where O.E == S {
|
|
||||||
return { source in
|
|
||||||
return { configureCell in
|
|
||||||
let dataSource = RxTableViewReactiveArrayDataSourceSequenceWrapper<S> { (tv, i, item) in
|
|
||||||
let indexPath = IndexPath(item: i, section: 0)
|
|
||||||
let cell = tv.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! Cell
|
|
||||||
configureCell(i, item, cell)
|
|
||||||
return cell
|
|
||||||
}
|
|
||||||
return self.items(dataSource: dataSource)(source)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Binds sequences of elements to table view rows.
|
|
||||||
|
|
||||||
- parameter cellIdentifier: Identifier used to dequeue cells.
|
- parameter cellIdentifier: Identifier used to dequeue cells.
|
||||||
- parameter source: Observable sequence of items.
|
- parameter source: Observable sequence of items.
|
||||||
- parameter configureCell: Transform between sequence elements and view cells.
|
- parameter configureCell: Transform between sequence elements and view cells.
|
||||||
|
|
@ -175,70 +95,6 @@ extension Reactive where Base: UITableView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Binds sequences of elements to table view rows using a custom reactive data used to perform the transformation.
|
|
||||||
This method will retain the data source for as long as the subscription isn't disposed (result `Disposable`
|
|
||||||
being disposed).
|
|
||||||
In case `source` observable sequence terminates sucessfully, the data source will present latest element
|
|
||||||
until the subscription isn't disposed.
|
|
||||||
|
|
||||||
- parameter dataSource: Data source used to transform elements to view cells.
|
|
||||||
- parameter source: Observable sequence of items.
|
|
||||||
- returns: Disposable object that can be used to unbind.
|
|
||||||
|
|
||||||
Example
|
|
||||||
|
|
||||||
let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, Double>>()
|
|
||||||
|
|
||||||
let items = Observable.just([
|
|
||||||
SectionModel(model: "First section", items: [
|
|
||||||
1.0,
|
|
||||||
2.0,
|
|
||||||
3.0
|
|
||||||
]),
|
|
||||||
SectionModel(model: "Second section", items: [
|
|
||||||
1.0,
|
|
||||||
2.0,
|
|
||||||
3.0
|
|
||||||
]),
|
|
||||||
SectionModel(model: "Third section", items: [
|
|
||||||
1.0,
|
|
||||||
2.0,
|
|
||||||
3.0
|
|
||||||
])
|
|
||||||
])
|
|
||||||
|
|
||||||
dataSource.configureCell = { (dataSource, tv, indexPath, element) in
|
|
||||||
let cell = tv.dequeueReusableCellWithIdentifier("Cell")!
|
|
||||||
cell.textLabel?.text = "\(element) @ row \(indexPath.row)"
|
|
||||||
return cell
|
|
||||||
}
|
|
||||||
|
|
||||||
items
|
|
||||||
.bindTo(tableView.rx.itemsWithDataSource(dataSource))
|
|
||||||
.addDisposableTo(disposeBag)
|
|
||||||
*/
|
|
||||||
@available(*, deprecated, renamed: "items(dataSource:source:)")
|
|
||||||
public func rx_itemsWithDataSource<
|
|
||||||
DataSource: RxTableViewDataSourceType & UITableViewDataSource,
|
|
||||||
O: ObservableType>
|
|
||||||
(_ dataSource: DataSource)
|
|
||||||
-> (_ source: O)
|
|
||||||
-> Disposable
|
|
||||||
where DataSource.Element == O.E
|
|
||||||
{
|
|
||||||
return { source in
|
|
||||||
// There needs to be a strong retaining here because
|
|
||||||
return source.subscribeProxyDataSource(ofObject: self.base, dataSource: dataSource, retainDataSource: true) { [weak tableView = self.base] (_: RxTableViewDataSourceProxy, event) -> Void in
|
|
||||||
guard let tableView = tableView else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
dataSource.tableView(tableView, observedEvent: event)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Binds sequences of elements to table view rows using a custom reactive data used to perform the transformation.
|
Binds sequences of elements to table view rows using a custom reactive data used to perform the transformation.
|
||||||
|
|
@ -274,7 +130,7 @@ extension Reactive where Base: UITableView {
|
||||||
])
|
])
|
||||||
|
|
||||||
dataSource.configureCell = { (dataSource, tv, indexPath, element) in
|
dataSource.configureCell = { (dataSource, tv, indexPath, element) in
|
||||||
let cell = tv.dequeueReusableCellWithIdentifier("Cell")!
|
let cell = tv.dequeueReusableCellWithIdentifier("Cell")!
|
||||||
cell.textLabel?.text = "\(element) @ row \(indexPath.row)"
|
cell.textLabel?.text = "\(element) @ row \(indexPath.row)"
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
|
|
@ -477,7 +333,7 @@ extension Reactive where Base: UITableView {
|
||||||
return Observable.empty()
|
return Observable.empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
return Observable.just(try view.rx.modelAtIndexPath(indexPath))
|
return Observable.just(try view.rx.model(indexPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
return ControlEvent(events: source)
|
return ControlEvent(events: source)
|
||||||
|
|
@ -500,7 +356,7 @@ extension Reactive where Base: UITableView {
|
||||||
return Observable.empty()
|
return Observable.empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
return Observable.just(try view.rx.modelAtIndexPath(indexPath))
|
return Observable.just(try view.rx.model(indexPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
return ControlEvent(events: source)
|
return ControlEvent(events: source)
|
||||||
|
|
@ -509,10 +365,10 @@ extension Reactive where Base: UITableView {
|
||||||
/**
|
/**
|
||||||
Synchronous helper method for retrieving a model at indexPath through a reactive data source.
|
Synchronous helper method for retrieving a model at indexPath through a reactive data source.
|
||||||
*/
|
*/
|
||||||
public func modelAtIndexPath<T>(_ indexPath: IndexPath) throws -> T {
|
public func model<T>(_ indexPath: IndexPath) throws -> T {
|
||||||
let dataSource: SectionedViewDataSourceType = castOrFatalError(self.dataSource.forwardToDelegate(), message: "This method only works in case one of the `rx.items*` methods was used.")
|
let dataSource: SectionedViewDataSourceType = castOrFatalError(self.dataSource.forwardToDelegate(), message: "This method only works in case one of the `rx.items*` methods was used.")
|
||||||
|
|
||||||
let element = try dataSource.modelAtIndexPath(indexPath)
|
let element = try dataSource.model(indexPath)
|
||||||
|
|
||||||
return castOrFatalError(element)
|
return castOrFatalError(element)
|
||||||
}
|
}
|
||||||
|
|
@ -540,3 +396,145 @@ extension Reactive where Base: UITableView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// deprecated APIs
|
||||||
|
extension UITableView {
|
||||||
|
|
||||||
|
/**
|
||||||
|
Binds sequences of elements to table view rows.
|
||||||
|
|
||||||
|
- parameter source: Observable sequence of items.
|
||||||
|
- parameter cellFactory: Transform between sequence elements and view cells.
|
||||||
|
- returns: Disposable object that can be used to unbind.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
let items = Observable.just([
|
||||||
|
"First Item",
|
||||||
|
"Second Item",
|
||||||
|
"Third Item"
|
||||||
|
])
|
||||||
|
|
||||||
|
items
|
||||||
|
.bindTo(tableView.rx.itemsWithCellFactory) { (tableView, row, element) in
|
||||||
|
let cell = tableView.dequeueReusableCellWithIdentifier("Cell")!
|
||||||
|
cell.textLabel?.text = "\(element) @ row \(row)"
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
.addDisposableTo(disposeBag)
|
||||||
|
|
||||||
|
*/
|
||||||
|
@available(*, deprecated, renamed: "items(_:_:)")
|
||||||
|
public func rx_itemsWithCellFactory<S: Sequence, O: ObservableType>
|
||||||
|
(_ source: O)
|
||||||
|
-> (_ cellFactory: @escaping (UITableView, Int, S.Iterator.Element) -> UITableViewCell)
|
||||||
|
-> Disposable
|
||||||
|
where O.E == S {
|
||||||
|
return { cellFactory in
|
||||||
|
return self.rx.items(source)(cellFactory)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Binds sequences of elements to table view rows.
|
||||||
|
|
||||||
|
- parameter cellIdentifier: Identifier used to dequeue cells.
|
||||||
|
- parameter source: Observable sequence of items.
|
||||||
|
- parameter configureCell: Transform between sequence elements and view cells.
|
||||||
|
- parameter cellType: Type of table view cell.
|
||||||
|
- returns: Disposable object that can be used to unbind.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
let items = Observable.just([
|
||||||
|
"First Item",
|
||||||
|
"Second Item",
|
||||||
|
"Third Item"
|
||||||
|
])
|
||||||
|
|
||||||
|
items
|
||||||
|
.bindTo(tableView.rx.items(cellIdentifier: "Cell", cellType: UITableViewCell.self)) { (row, element, cell) in
|
||||||
|
cell.textLabel?.text = "\(element) @ row \(row)"
|
||||||
|
}
|
||||||
|
.addDisposableTo(disposeBag)
|
||||||
|
*/
|
||||||
|
@available(*, deprecated, renamed: "items(cellIdentifier:cellType:_:_:)")
|
||||||
|
public func rx_itemsWithCellIdentifier<S: Sequence, Cell: UITableViewCell, O : ObservableType>
|
||||||
|
(_ cellIdentifier: String, cellType: Cell.Type = Cell.self)
|
||||||
|
-> (_ source: O)
|
||||||
|
-> (_ configureCell: @escaping (Int, S.Iterator.Element, Cell) -> Void)
|
||||||
|
-> Disposable
|
||||||
|
where O.E == S {
|
||||||
|
return { source in
|
||||||
|
return { configureCell in
|
||||||
|
return self.rx.items(cellIdentifier: cellIdentifier, cellType: cellType)(source)(configureCell)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Binds sequences of elements to table view rows using a custom reactive data used to perform the transformation.
|
||||||
|
This method will retain the data source for as long as the subscription isn't disposed (result `Disposable`
|
||||||
|
being disposed).
|
||||||
|
In case `source` observable sequence terminates sucessfully, the data source will present latest element
|
||||||
|
until the subscription isn't disposed.
|
||||||
|
|
||||||
|
- parameter dataSource: Data source used to transform elements to view cells.
|
||||||
|
- parameter source: Observable sequence of items.
|
||||||
|
- returns: Disposable object that can be used to unbind.
|
||||||
|
|
||||||
|
Example
|
||||||
|
|
||||||
|
let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, Double>>()
|
||||||
|
|
||||||
|
let items = Observable.just([
|
||||||
|
SectionModel(model: "First section", items: [
|
||||||
|
1.0,
|
||||||
|
2.0,
|
||||||
|
3.0
|
||||||
|
]),
|
||||||
|
SectionModel(model: "Second section", items: [
|
||||||
|
1.0,
|
||||||
|
2.0,
|
||||||
|
3.0
|
||||||
|
]),
|
||||||
|
SectionModel(model: "Third section", items: [
|
||||||
|
1.0,
|
||||||
|
2.0,
|
||||||
|
3.0
|
||||||
|
])
|
||||||
|
])
|
||||||
|
|
||||||
|
dataSource.configureCell = { (dataSource, tv, indexPath, element) in
|
||||||
|
let cell = tv.dequeueReusableCellWithIdentifier("Cell")!
|
||||||
|
cell.textLabel?.text = "\(element) @ row \(indexPath.row)"
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
|
||||||
|
items
|
||||||
|
.bindTo(tableView.rx.items(dataSoruce: dataSource))
|
||||||
|
.addDisposableTo(disposeBag)
|
||||||
|
*/
|
||||||
|
@available(*, deprecated, renamed: "items(dataSource:_:)")
|
||||||
|
public func rx_itemsWithDataSource<
|
||||||
|
DataSource: RxTableViewDataSourceType & UITableViewDataSource,
|
||||||
|
O: ObservableType>
|
||||||
|
(_ dataSource: DataSource)
|
||||||
|
-> (_ source: O)
|
||||||
|
-> Disposable
|
||||||
|
where DataSource.Element == O.E
|
||||||
|
{
|
||||||
|
return { source in
|
||||||
|
return self.rx.items(dataSource: dataSource)(source)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Synchronous helper method for retrieving a model at indexPath through a reactive data source.
|
||||||
|
*/
|
||||||
|
@available(*, deprecated, renamed: "rx.model(_:)")
|
||||||
|
public func rx_modelAtIndexPath<T>(_ indexPath: IndexPath) throws -> T {
|
||||||
|
return try self.rx.model(indexPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -99,17 +99,24 @@ public class CollectionViewSectionedDataSource<S: SectionModelType>
|
||||||
return _sectionModels.map { Section(original: $0.model, items: $0.items) }
|
return _sectionModels.map { Section(original: $0.model, items: $0.items) }
|
||||||
}
|
}
|
||||||
|
|
||||||
public func sectionAtIndex(_ section: Int) -> S {
|
public subscript(section: Int) -> S {
|
||||||
let sectionModel = self._sectionModels[section]
|
let sectionModel = self._sectionModels[section]
|
||||||
return S(original: sectionModel.model, items: sectionModel.items)
|
return S(original: sectionModel.model, items: sectionModel.items)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func itemAtIndexPath(_ indexPath: IndexPath) -> I {
|
public subscript(indexPath: IndexPath) -> I {
|
||||||
return self._sectionModels[indexPath.section].items[indexPath.item]
|
get {
|
||||||
|
return self._sectionModels[indexPath.section].items[indexPath.item]
|
||||||
|
}
|
||||||
|
set(item) {
|
||||||
|
var section = self._sectionModels[indexPath.section]
|
||||||
|
section.items[indexPath.item] = item
|
||||||
|
self._sectionModels[indexPath.section] = section
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func modelAtIndexPath(_ indexPath: IndexPath) throws -> Any {
|
public func model(_ indexPath: IndexPath) throws -> Any {
|
||||||
return itemAtIndexPath(indexPath)
|
return self[indexPath]
|
||||||
}
|
}
|
||||||
|
|
||||||
public func setSections(_ sections: [S]) {
|
public func setSections(_ sections: [S]) {
|
||||||
|
|
@ -188,7 +195,7 @@ public class CollectionViewSectionedDataSource<S: SectionModelType>
|
||||||
override func _rx_collectionView(_ collectionView: UICollectionView, cellForItemAtIndexPath indexPath: IndexPath) -> UICollectionViewCell {
|
override func _rx_collectionView(_ collectionView: UICollectionView, cellForItemAtIndexPath indexPath: IndexPath) -> UICollectionViewCell {
|
||||||
precondition(indexPath.item < _sectionModels[indexPath.section].items.count)
|
precondition(indexPath.item < _sectionModels[indexPath.section].items.count)
|
||||||
|
|
||||||
return configureCell(self, collectionView, indexPath, itemAtIndexPath(indexPath))
|
return configureCell(self, collectionView, indexPath, self[indexPath])
|
||||||
}
|
}
|
||||||
|
|
||||||
override func _rx_collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: IndexPath) -> UICollectionReusableView {
|
override func _rx_collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: IndexPath) -> UICollectionReusableView {
|
||||||
|
|
|
||||||
|
|
@ -139,18 +139,19 @@ public class RxTableViewSectionedDataSource<S: SectionModelType>
|
||||||
return Section(original: sectionModel.model, items: sectionModel.items)
|
return Section(original: sectionModel.model, items: sectionModel.items)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func itemAtIndexPath(_ indexPath: IndexPath) -> I {
|
public subscript(indexPath: IndexPath) -> I {
|
||||||
return self._sectionModels[indexPath.section].items[indexPath.item]
|
get {
|
||||||
|
return self._sectionModels[indexPath.section].items[indexPath.item]
|
||||||
|
}
|
||||||
|
set(item) {
|
||||||
|
var section = self._sectionModels[indexPath.section]
|
||||||
|
section.items[indexPath.item] = item
|
||||||
|
self._sectionModels[indexPath.section] = section
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func setItem(item: I, indexPath: IndexPath) {
|
public func model(_ indexPath: IndexPath) throws -> Any {
|
||||||
var section = self._sectionModels[indexPath.section]
|
return self[indexPath]
|
||||||
section.items[indexPath.item] = item
|
|
||||||
self._sectionModels[indexPath.section] = section
|
|
||||||
}
|
|
||||||
|
|
||||||
public func modelAtIndexPath(_ indexPath: IndexPath) throws -> Any {
|
|
||||||
return itemAtIndexPath(indexPath)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func setSections(_ sections: [S]) {
|
public func setSections(_ sections: [S]) {
|
||||||
|
|
@ -238,7 +239,7 @@ public class RxTableViewSectionedDataSource<S: SectionModelType>
|
||||||
override func _rx_tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: IndexPath) -> UITableViewCell {
|
override func _rx_tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: IndexPath) -> UITableViewCell {
|
||||||
precondition(indexPath.item < _sectionModels[indexPath.section].items.count)
|
precondition(indexPath.item < _sectionModels[indexPath.section].items.count)
|
||||||
|
|
||||||
return configureCell(self, tableView, indexPath, itemAtIndexPath(indexPath))
|
return configureCell(self, tableView, indexPath, self[indexPath])
|
||||||
}
|
}
|
||||||
|
|
||||||
override func _rx_tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
override func _rx_tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ class SimpleTableViewExampleSectionedViewController
|
||||||
tableView.rx
|
tableView.rx
|
||||||
.itemSelected
|
.itemSelected
|
||||||
.map { indexPath in
|
.map { indexPath in
|
||||||
return (indexPath, dataSource.itemAtIndexPath(indexPath))
|
return (indexPath, dataSource[indexPath])
|
||||||
}
|
}
|
||||||
.subscribe(onNext: { indexPath, model in
|
.subscribe(onNext: { indexPath, model in
|
||||||
DefaultWireframe.presentAlert("Tapped `\(model)` @ \(indexPath)")
|
DefaultWireframe.presentAlert("Tapped `\(model)` @ \(indexPath)")
|
||||||
|
|
|
||||||
|
|
@ -164,7 +164,7 @@ class PartialUpdatesViewController : ViewController {
|
||||||
dataSource.supplementaryViewFactory = { (dataSource, cv, kind, ip) in
|
dataSource.supplementaryViewFactory = { (dataSource, cv, kind, ip) in
|
||||||
let section = cv.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "Section", for: ip) as! NumberSectionView
|
let section = cv.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "Section", for: ip) as! NumberSectionView
|
||||||
|
|
||||||
section.value!.text = "\(dataSource.sectionAtIndex(ip.section).model)"
|
section.value!.text = "\(dataSource[ip.section].model)"
|
||||||
|
|
||||||
return section
|
return section
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ import UIKit
|
||||||
super.init()
|
super.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
func modelAtIndexPath(_ indexPath: IndexPath) throws -> Any {
|
func model(_ indexPath: IndexPath) throws -> Any {
|
||||||
return items![indexPath.item]
|
return items![indexPath.item]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -248,7 +248,7 @@ class UICollectionViewTests : RxTest {
|
||||||
}
|
}
|
||||||
let (collectionView, dataSourceSubscription) = createView()
|
let (collectionView, dataSourceSubscription) = createView()
|
||||||
|
|
||||||
let model: Int = try! collectionView.rx.modelAtIndexPath(IndexPath(item: 1, section: 0))
|
let model: Int = try! collectionView.rx.model(IndexPath(item: 1, section: 0))
|
||||||
|
|
||||||
XCTAssertEqual(model, 2)
|
XCTAssertEqual(model, 2)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -352,7 +352,7 @@ class UITableViewTests : RxTest {
|
||||||
|
|
||||||
let (tableView, dataSourceSubscription) = createView()
|
let (tableView, dataSourceSubscription) = createView()
|
||||||
|
|
||||||
let model: Int = try! tableView.rx.modelAtIndexPath(IndexPath(item: 1, section: 0))
|
let model: Int = try! tableView.rx.model(IndexPath(item: 1, section: 0))
|
||||||
|
|
||||||
XCTAssertEqual(model, 2)
|
XCTAssertEqual(model, 2)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue