From 3294458b8763e3a3adb2aadbdc9e45c65ed35a5f Mon Sep 17 00:00:00 2001 From: Krunoslav Zaher Date: Mon, 18 Apr 2016 23:10:32 +0200 Subject: [PATCH] Adds `rx_willDisplayCell` and `rx_didEndDisplayingCell` to `UITableView`. --- RxCocoa/iOS/Events/ItemEvents.swift | 6 ++- RxCocoa/iOS/UITableView+Rx.swift | 44 +++++++++++++++----- Tests/RxCocoaTests/UITableView+RxTests.swift | 44 ++++++++++++++++++++ 3 files changed, 83 insertions(+), 11 deletions(-) diff --git a/RxCocoa/iOS/Events/ItemEvents.swift b/RxCocoa/iOS/Events/ItemEvents.swift index ecbe6e99..947ef2aa 100644 --- a/RxCocoa/iOS/Events/ItemEvents.swift +++ b/RxCocoa/iOS/Events/ItemEvents.swift @@ -9,4 +9,8 @@ import Foundation import UIKit -public typealias ItemMovedEvent = (sourceIndex: NSIndexPath, destinationIndex: NSIndexPath) \ No newline at end of file +#if os(iOS) || os(tvOS) +public typealias ItemMovedEvent = (sourceIndex: NSIndexPath, destinationIndex: NSIndexPath) +public typealias WillDisplayCellEvent = (cell: UITableViewCell, indexPath: NSIndexPath) +public typealias DidEndDisplayingCellEvent = (cell: UITableViewCell, indexPath: NSIndexPath) +#endif \ No newline at end of file diff --git a/RxCocoa/iOS/UITableView+Rx.swift b/RxCocoa/iOS/UITableView+Rx.swift index 50661401..a8137199 100644 --- a/RxCocoa/iOS/UITableView+Rx.swift +++ b/RxCocoa/iOS/UITableView+Rx.swift @@ -137,7 +137,7 @@ extension UITableView { public var rx_itemSelected: ControlEvent { let source = rx_delegate.observe(#selector(UITableViewDelegate.tableView(_:didSelectRowAtIndexPath:))) .map { a in - return a[1] as! NSIndexPath + return try castOrThrow(NSIndexPath.self, a[1]) } return ControlEvent(events: source) @@ -149,7 +149,7 @@ extension UITableView { public var rx_itemDeselected: ControlEvent { let source = rx_delegate.observe(#selector(UITableViewDelegate.tableView(_:didDeselectRowAtIndexPath:))) .map { a in - return a[1] as! NSIndexPath + return try castOrThrow(NSIndexPath.self, a[1]) } return ControlEvent(events: source) @@ -161,7 +161,7 @@ extension UITableView { public var rx_itemAccessoryButtonTapped: ControlEvent { let source: Observable = rx_delegate.observe(#selector(UITableViewDelegate.tableView(_:accessoryButtonTappedForRowWithIndexPath:))) .map { a in - return a[1] as! NSIndexPath + return try castOrThrow(NSIndexPath.self, a[1]) } return ControlEvent(events: source) @@ -173,10 +173,10 @@ extension UITableView { public var rx_itemInserted: ControlEvent { let source = rx_dataSource.observe(#selector(UITableViewDataSource.tableView(_:commitEditingStyle:forRowAtIndexPath:))) .filter { a in - return UITableViewCellEditingStyle(rawValue: (a[1] as! NSNumber).integerValue) == .Insert + return UITableViewCellEditingStyle(rawValue: (try castOrThrow(NSNumber.self, a[1])).integerValue) == .Insert } .map { a in - return (a[2] as! NSIndexPath) + return (try castOrThrow(NSIndexPath.self, a[2])) } return ControlEvent(events: source) @@ -188,10 +188,10 @@ extension UITableView { public var rx_itemDeleted: ControlEvent { let source = rx_dataSource.observe(#selector(UITableViewDataSource.tableView(_:commitEditingStyle:forRowAtIndexPath:))) .filter { a in - return UITableViewCellEditingStyle(rawValue: (a[1] as! NSNumber).integerValue) == .Delete + return UITableViewCellEditingStyle(rawValue: (try castOrThrow(NSNumber.self, a[1])).integerValue) == .Delete } .map { a in - return (a[2] as! NSIndexPath) + return try castOrThrow(NSIndexPath.self, a[2]) } return ControlEvent(events: source) @@ -203,12 +203,36 @@ extension UITableView { public var rx_itemMoved: ControlEvent { let source: Observable = rx_dataSource.observe(#selector(UITableViewDataSource.tableView(_:moveRowAtIndexPath:toIndexPath:))) .map { a in - return ((a[1] as! NSIndexPath), (a[2] as! NSIndexPath)) + return (try castOrThrow(NSIndexPath.self, a[1]), try castOrThrow(NSIndexPath.self, a[2])) } return ControlEvent(events: source) } - + + /** + Reactive wrapper for `delegate` message `tableView:willDisplayCell:forRowAtIndexPath:`. + */ + public var rx_willDisplayCell: ControlEvent { + let source: Observable = rx_delegate.observe(#selector(UITableViewDelegate.tableView(_:willDisplayCell:forRowAtIndexPath:))) + .map { a in + return (try castOrThrow(UITableViewCell.self, a[1]), try castOrThrow(NSIndexPath.self, a[2])) + } + + return ControlEvent(events: source) + } + + /** + Reactive wrapper for `delegate` message `tableView:didEndDisplayingCell:forRowAtIndexPath:`. + */ + public var rx_didEndDisplayingCell: ControlEvent { + let source: Observable = rx_delegate.observe(#selector(UITableViewDelegate.tableView(_:didEndDisplayingCell:forRowAtIndexPath:))) + .map { a in + return (try castOrThrow(UITableViewCell.self, a[1]), try castOrThrow(NSIndexPath.self, a[2])) + } + + return ControlEvent(events: source) + } + /** Reactive wrapper for `delegate` message `tableView:didSelectRowAtIndexPath:`. @@ -281,7 +305,7 @@ extension UITableView { let source = rx_delegate.observe(#selector(UITableViewDelegate.tableView(_:didUpdateFocusInContext:withAnimationCoordinator:))) .map { a -> (context: UIFocusUpdateContext, animationCoordinator: UIFocusAnimationCoordinator) in let context = a[1] as! UIFocusUpdateContext - let animationCoordinator = a[2] as! UIFocusAnimationCoordinator + let animationCoordinator = try castOrThrow(UIFocusAnimationCoordinator.self, a[2]) return (context: context, animationCoordinator: animationCoordinator) } diff --git a/Tests/RxCocoaTests/UITableView+RxTests.swift b/Tests/RxCocoaTests/UITableView+RxTests.swift index 8b4da80c..8a83859e 100644 --- a/Tests/RxCocoaTests/UITableView+RxTests.swift +++ b/Tests/RxCocoaTests/UITableView+RxTests.swift @@ -24,6 +24,8 @@ class UITableViewTests : RxTest { ensureEventDeallocated(createView) { (view: UITableView) in view.rx_itemInserted } ensureEventDeallocated(createView) { (view: UITableView) in view.rx_modelSelected(Int.self) } ensureEventDeallocated(createView) { (view: UITableView) in view.rx_modelDeselected(Int.self) } + ensureEventDeallocated(createView) { (view: UITableView) in view.rx_willDisplayCell } + ensureEventDeallocated(createView) { (view: UITableView) in view.rx_didEndDisplayingCell } } func testTableView_itemSelected() { @@ -111,6 +113,48 @@ class UITableViewTests : RxTest { subscription.dispose() } + func testTableView_willDisplayCell() { + let tableView = UITableView(frame: CGRectMake(0, 0, 1, 1)) + + var resultIndexPath: NSIndexPath? = nil + var resultCell: UITableViewCell? = nil + + let subscription = tableView.rx_willDisplayCell + .subscribeNext { (cell, indexPath) in + resultIndexPath = indexPath + resultCell = cell + } + + let testRow = NSIndexPath(forRow: 1, inSection: 0) + let testCell = UITableViewCell() + tableView.delegate!.tableView!(tableView, willDisplayCell: testCell, forRowAtIndexPath: testRow) + + XCTAssertEqual(resultIndexPath, testRow) + XCTAssertEqual(resultCell, testCell) + subscription.dispose() + } + + func testTableView_didEndDisplayingCell() { + let tableView = UITableView(frame: CGRectMake(0, 0, 1, 1)) + + var resultIndexPath: NSIndexPath? = nil + var resultCell: UITableViewCell? = nil + + let subscription = tableView.rx_didEndDisplayingCell + .subscribeNext { (cell, indexPath) in + resultIndexPath = indexPath + resultCell = cell + } + + let testRow = NSIndexPath(forRow: 1, inSection: 0) + let testCell = UITableViewCell() + tableView.delegate!.tableView!(tableView, didEndDisplayingCell: testCell, forRowAtIndexPath: testRow) + + XCTAssertEqual(resultIndexPath, testRow) + XCTAssertEqual(resultCell, testCell) + subscription.dispose() + } + func testTableView_itemMoved() { let tableView = UITableView(frame: CGRectMake(0, 0, 1, 1))