From 43269fa279b3d5ec78b26de7b08abb8935a8c4e6 Mon Sep 17 00:00:00 2001 From: sergdort Date: Fri, 13 May 2016 10:55:21 +0300 Subject: [PATCH] Added `rx_itemSelected` for UIPickerView --- Rx.xcodeproj/project.pbxproj | 20 +++++++++ .../Proxies/RxPickerViewDelegateProxy.swift | 38 +++++++++++++++++ RxCocoa/iOS/UIPickerView+Rx.swift | 36 ++++++++++++++++ .../DelegateProxyTest+UIKit.swift | 30 ++++++++++++++ Tests/RxCocoaTests/UIPickerView+RxTests.swift | 41 +++++++++++++++++++ 5 files changed, 165 insertions(+) create mode 100644 RxCocoa/iOS/Proxies/RxPickerViewDelegateProxy.swift create mode 100644 RxCocoa/iOS/UIPickerView+Rx.swift create mode 100644 Tests/RxCocoaTests/UIPickerView+RxTests.swift diff --git a/Rx.xcodeproj/project.pbxproj b/Rx.xcodeproj/project.pbxproj index 5c7d50a0..4637b78e 100644 --- a/Rx.xcodeproj/project.pbxproj +++ b/Rx.xcodeproj/project.pbxproj @@ -29,6 +29,13 @@ 842A5A2C1C357F92003568D5 /* NSTextStorage+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842A5A281C357F7D003568D5 /* NSTextStorage+Rx.swift */; }; 842A5A2D1C357F93003568D5 /* NSTextStorage+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842A5A281C357F7D003568D5 /* NSTextStorage+Rx.swift */; }; 842A5A2E1C357F94003568D5 /* NSTextStorage+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842A5A281C357F7D003568D5 /* NSTextStorage+Rx.swift */; }; + 844BC8AC1CE4FA6300F5C7CB /* RxPickerViewDelegateProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BC8AA1CE4FA5600F5C7CB /* RxPickerViewDelegateProxy.swift */; }; + 844BC8AD1CE4FA6400F5C7CB /* RxPickerViewDelegateProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BC8AA1CE4FA5600F5C7CB /* RxPickerViewDelegateProxy.swift */; }; + 844BC8AE1CE4FA6600F5C7CB /* RxPickerViewDelegateProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BC8AA1CE4FA5600F5C7CB /* RxPickerViewDelegateProxy.swift */; }; + 844BC8B41CE4FD7500F5C7CB /* UIPickerView+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BC8B31CE4FD7500F5C7CB /* UIPickerView+Rx.swift */; }; + 844BC8B51CE4FD7500F5C7CB /* UIPickerView+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BC8B31CE4FD7500F5C7CB /* UIPickerView+Rx.swift */; }; + 844BC8B61CE4FD7500F5C7CB /* UIPickerView+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BC8B31CE4FD7500F5C7CB /* UIPickerView+Rx.swift */; }; + 844BC8BB1CE5024500F5C7CB /* UIPickerView+RxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BC8B71CE5023200F5C7CB /* UIPickerView+RxTests.swift */; }; 846436E31C9AF65B0035B40D /* RxSearchControllerDelegateProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 846436E11C9AF64C0035B40D /* RxSearchControllerDelegateProxy.swift */; }; 846436E51C9AF65E0035B40D /* RxSearchControllerDelegateProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 846436E11C9AF64C0035B40D /* RxSearchControllerDelegateProxy.swift */; }; 846436E61C9AF6670035B40D /* RxSearchControllerDelegateProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 846436E11C9AF64C0035B40D /* RxSearchControllerDelegateProxy.swift */; }; @@ -1351,6 +1358,9 @@ 7F600F3D1C5D0C0100535B1D /* UIRefreshControl+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIRefreshControl+Rx.swift"; sourceTree = ""; }; 7F600F421C5D0D2D00535B1D /* UIRefreshControl+RxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIRefreshControl+RxTests.swift"; sourceTree = ""; }; 842A5A281C357F7D003568D5 /* NSTextStorage+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSTextStorage+Rx.swift"; sourceTree = ""; }; + 844BC8AA1CE4FA5600F5C7CB /* RxPickerViewDelegateProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxPickerViewDelegateProxy.swift; sourceTree = ""; }; + 844BC8B31CE4FD7500F5C7CB /* UIPickerView+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIPickerView+Rx.swift"; sourceTree = ""; }; + 844BC8B71CE5023200F5C7CB /* UIPickerView+RxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIPickerView+RxTests.swift"; sourceTree = ""; }; 846436E11C9AF64C0035B40D /* RxSearchControllerDelegateProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxSearchControllerDelegateProxy.swift; sourceTree = ""; }; 8476A01F1C3D5D580040BA22 /* UIImagePickerController+RxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImagePickerController+RxTests.swift"; sourceTree = ""; }; 8479BC441C3ACDA400FB8B54 /* RxImagePickerDelegateProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxImagePickerDelegateProxy.swift; sourceTree = ""; }; @@ -2249,6 +2259,7 @@ C8C217D41CB7100E0038A2E6 /* UITableView+RxTests.swift */, C8C217D61CB710200038A2E6 /* UICollectionView+RxTests.swift */, 54700C9E1CE37D1000EF3A8F /* UINavigationItem+RxTests.swift.swift */, + 844BC8B71CE5023200F5C7CB /* UIPickerView+RxTests.swift */, ); path = RxCocoaTests; sourceTree = ""; @@ -2389,6 +2400,7 @@ 7EDBAEB71C89B9B7006CBE67 /* UITabBarItem+Rx.swift */, 84E4D3901C9AFCD500ADFDC9 /* UISearchController+Rx.swift */, 54D2138C1CE081890028D5B4 /* UINavigationItem+Rx.swift */, + 844BC8B31CE4FD7500F5C7CB /* UIPickerView+Rx.swift */, ); path = iOS; sourceTree = ""; @@ -2432,6 +2444,7 @@ 84C225A21C33F00B008724EC /* RxTextStorageDelegateProxy.swift */, 8479BC441C3ACDA400FB8B54 /* RxImagePickerDelegateProxy.swift */, 846436E11C9AF64C0035B40D /* RxSearchControllerDelegateProxy.swift */, + 844BC8AA1CE4FA5600F5C7CB /* RxPickerViewDelegateProxy.swift */, ); path = Proxies; sourceTree = ""; @@ -3267,6 +3280,7 @@ C88254321B8A752B00B02D69 /* UISlider+Rx.swift in Sources */, C8093ED91B8A732E0088E94D /* _RXKVOObserver.m in Sources */, C882542F1B8A752B00B02D69 /* UIScrollView+Rx.swift in Sources */, + 844BC8B41CE4FD7500F5C7CB /* UIPickerView+Rx.swift in Sources */, C80DDE9B1BCE69BA006A1832 /* Driver+Operators.swift in Sources */, C8093EE31B8A732E0088E94D /* DelegateProxyType.swift in Sources */, C8093EFD1B8A732E0088E94D /* RxTarget.swift in Sources */, @@ -3304,6 +3318,7 @@ 7EDBAEBC1C89B9B7006CBE67 /* UITabBarItem+Rx.swift in Sources */, C839365F1C70E02200A9A09E /* UIApplication+Rx.swift in Sources */, C80DDE9F1BCE69BA006A1832 /* Driver+Subscription.swift in Sources */, + 844BC8AC1CE4FA6300F5C7CB /* RxPickerViewDelegateProxy.swift in Sources */, C811C89D1C24D80100A2DDD4 /* DeallocObservable.swift in Sources */, C8BCD3ED1C14B5FB005F1280 /* UIView+Rx.swift in Sources */, C80D338F1B91EF9E0014629D /* Observable+Bind.swift in Sources */, @@ -3433,6 +3448,7 @@ C835094B1C38706E0027C24C /* AnonymousObservable+Test.swift in Sources */, C8C217D51CB7100E0038A2E6 /* UITableView+RxTests.swift in Sources */, C835092E1C38706E0027C24C /* ControlEventTests.swift in Sources */, + 844BC8BB1CE5024500F5C7CB /* UIPickerView+RxTests.swift in Sources */, C83509531C38706E0027C24C /* Observable+AggregateTest.swift in Sources */, C8B290891C94D64600E923D0 /* RxTest+Controls.swift in Sources */, C83509291C38706E0027C24C /* PerformanceTools.swift in Sources */, @@ -4202,6 +4218,7 @@ C8F0C0161BBBFBB9001B112F /* UITableView+Rx.swift in Sources */, 84E4D3941C9AFD3600ADFDC9 /* UISearchController+Rx.swift in Sources */, C8F0C0171BBBFBB9001B112F /* RxCollectionViewReactiveArrayDataSource.swift in Sources */, + 844BC8B61CE4FD7500F5C7CB /* UIPickerView+Rx.swift in Sources */, 54D213931CE08DDB0028D5B4 /* UINavigationItem+Rx.swift in Sources */, C8C4B4AC1C17722400828BD5 /* _RXObjCRuntime.m in Sources */, C8F0C0181BBBFBB9001B112F /* KVOObserver.swift in Sources */, @@ -4231,6 +4248,7 @@ C8F0C02B1BBBFBB9001B112F /* ControlProperty.swift in Sources */, C8F0C02C1BBBFBB9001B112F /* UIDatePicker+Rx.swift in Sources */, C8F0C02D1BBBFBB9001B112F /* RxTableViewDataSourceProxy.swift in Sources */, + 844BC8AE1CE4FA6600F5C7CB /* RxPickerViewDelegateProxy.swift in Sources */, C8BCD3F71C14B6D1005F1280 /* NSLayoutConstraint+Rx.swift in Sources */, C8F0C0301BBBFBB9001B112F /* UIGestureRecognizer+Rx.swift in Sources */, C8F0C0311BBBFBB9001B112F /* DelegateProxy.swift in Sources */, @@ -4280,6 +4298,7 @@ D203C5081BB9C53E00D02D00 /* UIGestureRecognizer+Rx.swift in Sources */, D2138C931BB9BEDA00339B5C /* NSNotificationCenter+Rx.swift in Sources */, C80DDE991BCE69BA006A1832 /* ControlProperty+Driver.swift in Sources */, + 844BC8B51CE4FD7500F5C7CB /* UIPickerView+Rx.swift in Sources */, C80DDE951BCE69BA006A1832 /* ControlEvent+Driver.swift in Sources */, D203C4F61BB9C52E00D02D00 /* RxCollectionViewDataSourceType.swift in Sources */, 84C225A41C33F00B008724EC /* RxTextStorageDelegateProxy.swift in Sources */, @@ -4337,6 +4356,7 @@ 8479BC4D1C3ACF6E00FB8B54 /* UIImagePickerController+Rx.swift in Sources */, D203C4FE1BB9C53700D02D00 /* RxTableViewDataSourceProxy.swift in Sources */, D203C5001BB9C53700D02D00 /* RxTextViewDelegateProxy.swift in Sources */, + 844BC8AD1CE4FA6400F5C7CB /* RxPickerViewDelegateProxy.swift in Sources */, C8DB96851BF754C80084BD53 /* NSObject+Rx+KVORepresentable.swift in Sources */, D203C5091BB9C53E00D02D00 /* UIImageView+Rx.swift in Sources */, D2138C871BB9BEBE00339B5C /* CLLocationManager+Rx.swift in Sources */, diff --git a/RxCocoa/iOS/Proxies/RxPickerViewDelegateProxy.swift b/RxCocoa/iOS/Proxies/RxPickerViewDelegateProxy.swift new file mode 100644 index 00000000..024f74c8 --- /dev/null +++ b/RxCocoa/iOS/Proxies/RxPickerViewDelegateProxy.swift @@ -0,0 +1,38 @@ +// +// RxPickerViewDelegateProxy.swift +// Rx +// +// Created by Segii Shulga on 5/12/16. +// Copyright © 2016 Krunoslav Zaher. All rights reserved. +// + +#if os(iOS) + + import Foundation +#if !RX_NO_MODULE + import RxSwift +#endif +import UIKit + +public class RxPickerViewDelegateProxy + : DelegateProxy + , DelegateProxyType + , UIPickerViewDelegate { + + /** + For more information take a look at `DelegateProxyType`. + */ + public class func setCurrentDelegate(delegate: AnyObject?, toObject object: AnyObject) { + let pickerView: UIPickerView = castOrFatalError(object) + pickerView.delegate = castOptionalOrFatalError(delegate) + } + + /** + For more information take a look at `DelegateProxyType`. + */ + public class func currentDelegateFor(object: AnyObject) -> AnyObject? { + let pickerView: UIPickerView = castOrFatalError(object) + return pickerView.delegate + } +} +#endif diff --git a/RxCocoa/iOS/UIPickerView+Rx.swift b/RxCocoa/iOS/UIPickerView+Rx.swift new file mode 100644 index 00000000..5006dc50 --- /dev/null +++ b/RxCocoa/iOS/UIPickerView+Rx.swift @@ -0,0 +1,36 @@ +// +// UIPickerView+Rx.swift +// Rx +// +// Created by Segii Shulga on 5/12/16. +// Copyright © 2016 Krunoslav Zaher. All rights reserved. +// + +#if os(iOS) + + import Foundation +#if !RX_NO_MODULE + import RxSwift +#endif + import UIKit + +extension UIPickerView { + /** + Reactive wrapper for `delegate`. + For more information take a look at `DelegateProxyType` protocol documentation. + */ + public var rx_delegate: DelegateProxy { + return RxPickerViewDelegateProxy.proxyForObject(self) + } + + public var rx_itemSelected: ControlEvent<(row: Int, component: Int)> { + let source = rx_delegate + .observe(#selector(UIPickerViewDelegate.pickerView(_:didSelectRow:inComponent:))) + .map { + return (try castOrThrow(Int.self, $0[1]), try castOrThrow(Int.self, $0[2])) + } + return ControlEvent(events: source) + } +} + +#endif diff --git a/Tests/RxCocoaTests/DelegateProxyTest+UIKit.swift b/Tests/RxCocoaTests/DelegateProxyTest+UIKit.swift index 1fd5c578..e7ab36fd 100644 --- a/Tests/RxCocoaTests/DelegateProxyTest+UIKit.swift +++ b/Tests/RxCocoaTests/DelegateProxyTest+UIKit.swift @@ -60,6 +60,8 @@ import XCTest #if os(iOS) extension RxSearchControllerDelegateProxy: TestDelegateProtocol { } +extension RxPickerViewDelegateProxy: TestDelegateProtocol { +} #endif // MARK: Tests @@ -124,6 +126,12 @@ extension DelegateProxyTest { performDelegateTest(UISearchControllerSubclass()) } } + +extension DelegateProxyTest { + func test_UIPickerViewExtension() { + performDelegateTest(UIPickerViewSubclass(frame: CGRect.zero)) + } +} #endif // MARK: Mocks @@ -379,4 +387,26 @@ class UISearchControllerSubclass return RxSearchControllerDelegateProxy.installForwardDelegate(testDelegate, retainDelegate: false, onProxyForObject: self) } } + +class UIPickerViewSubclass + : UIPickerView + , TestDelegateControl { + + func doThatTest(value: Int) { + (delegate as! TestDelegateProtocol).testEventHappened?(value) + } + + var test: Observable { + return rx_delegate + .observe(#selector(TestDelegateProtocol.testEventHappened(_:))) + .map { a in (a[0] as! NSNumber).integerValue } + } + + func setMineForwardDelegate(testDelegate: TestDelegateProtocol) -> Disposable { + return RxPickerViewDelegateProxy.installForwardDelegate(testDelegate, + retainDelegate: false, + onProxyForObject: self) + } +} + #endif diff --git a/Tests/RxCocoaTests/UIPickerView+RxTests.swift b/Tests/RxCocoaTests/UIPickerView+RxTests.swift new file mode 100644 index 00000000..5ddaf397 --- /dev/null +++ b/Tests/RxCocoaTests/UIPickerView+RxTests.swift @@ -0,0 +1,41 @@ +// +// UIPickerView+RxTests.swift +// Rx +// +// Created by Segii Shulga on 5/12/16. +// Copyright © 2016 Krunoslav Zaher. All rights reserved. +// + +import Foundation +import RxSwift +import RxCocoa +import UIKit +import XCTest + + +class UIPickerViewTests: RxTest { + + func testTableView_DelegateEventCompletesOnDealloc() { + let createView: () -> UIPickerView = { UIPickerView(frame: CGRectMake(0, 0, 1, 1)) } + + ensureEventDeallocated(createView) { (view: UIPickerView) in view.rx_itemSelected } + } + + func testPickerView_itemSelected() { + let pickerView = UIPickerView() + let row = 0 + let component = 0 + var result: (row: Int, component: Int)? + + autoreleasepool { + _ = pickerView.rx_itemSelected.subscribeNext { (element) in + result = element + } + pickerView.delegate!.pickerView!(pickerView, + didSelectRow: row, + inComponent: component) + } + XCTAssertEqual(result?.row, row) + XCTAssertEqual(result?.component, component) + } +}