Merge pull request #550 from stack/uisearchbar-cancel

UISearchBar Cancel Event
This commit is contained in:
Krunoslav Zaher 2016-04-10 12:57:13 +02:00
commit 18cf20820f
5 changed files with 143 additions and 4 deletions

View File

@ -1601,7 +1601,7 @@
C88254001B8A752B00B02D69 /* RxTableViewDataSourceProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxTableViewDataSourceProxy.swift; sourceTree = "<group>"; };
C88254011B8A752B00B02D69 /* RxTableViewDelegateProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxTableViewDelegateProxy.swift; sourceTree = "<group>"; };
C88254021B8A752B00B02D69 /* RxTextViewDelegateProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxTextViewDelegateProxy.swift; sourceTree = "<group>"; };
C88254051B8A752B00B02D69 /* UIBarButtonItem+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = "UIBarButtonItem+Rx.swift"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
C88254051B8A752B00B02D69 /* UIBarButtonItem+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = "UIBarButtonItem+Rx.swift"; sourceTree = "<group>"; };
C88254061B8A752B00B02D69 /* UIButton+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIButton+Rx.swift"; sourceTree = "<group>"; };
C88254071B8A752B00B02D69 /* UICollectionView+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UICollectionView+Rx.swift"; sourceTree = "<group>"; };
C88254081B8A752B00B02D69 /* UIControl+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = "UIControl+Rx.swift"; sourceTree = "<group>"; };

View File

@ -14,19 +14,33 @@ import UIKit
import RxSwift
#endif
class RxSearchBarDelegateProxy : DelegateProxy
public class RxSearchBarDelegateProxy : DelegateProxy
, UISearchBarDelegate
, DelegateProxyType {
class func currentDelegateFor(object: AnyObject) -> AnyObject? {
public class func currentDelegateFor(object: AnyObject) -> AnyObject? {
let searchBar: UISearchBar = castOrFatalError(object)
return searchBar.delegate
}
class func setCurrentDelegate(delegate: AnyObject?, toObject object: AnyObject) {
public class func setCurrentDelegate(delegate: AnyObject?, toObject object: AnyObject) {
let searchBar: UISearchBar = castOrFatalError(object)
searchBar.delegate = castOptionalOrFatalError(delegate)
}
// MARK: Delegate proxy methods
#if os(iOS)
/**
For more information take a look at `DelegateProxyType`.
*/
public override class func createProxyForObject(object: AnyObject) -> AnyObject {
let searchBar = (object as! UISearchBar)
return castOrFatalError(searchBar.rx_createDelegateProxy())
}
#endif
}
#endif

View File

@ -18,6 +18,17 @@ import UIKit
extension UISearchBar {
#if os(iOS)
/**
Factory method that enables subclasses to implement their own `rx_delegate`.
- returns: Instance of delegate proxy that wraps `delegate`.
*/
public func rx_createDelegateProxy() -> RxSearchBarDelegateProxy {
return RxSearchBarDelegateProxy(parentObject: self)
}
#endif
/**
Reactive wrapper for `delegate`.
@ -68,6 +79,30 @@ extension UISearchBar {
return ControlProperty(values: source, valueSink: bindingObserver)
}
#if os(iOS)
/**
Reactive wrapper for delegate method `searchBarCancelButtonClicked`.
*/
public var rx_cancelButtonClicked: ControlEvent<Void> {
let source: Observable<Void> = rx_delegate.observe(#selector(UISearchBarDelegate.searchBarCancelButtonClicked(_:)))
.map { _ in
return ()
}
return ControlEvent(events: source)
}
#endif
/**
Reactive wrapper for delegate method `searchBarSearchButtonClicked`.
*/
public var rx_searchButtonClicked: ControlEvent<Void> {
let source: Observable<Void> = rx_delegate.observe(#selector(UISearchBarDelegate.searchBarSearchButtonClicked(_:)))
.map { _ in
return ()
}
return ControlEvent(events: source)
}
}
#endif

View File

@ -44,6 +44,14 @@ import XCTest
optional func testEventHappened(value: Int)
}
#if os(iOS)
@objc protocol UISearchBarDelegateSubclass
: UISearchBarDelegate
, TestDelegateProtocol {
optional func testEventHappened(value: Int)
}
#endif
@objc protocol UITextViewDelegateSubclass
: UITextViewDelegate
, TestDelegateProtocol {
@ -91,6 +99,16 @@ extension DelegateProxyTest {
}
}
// MARK: UISearchBar
#if os(iOS)
extension DelegateProxyTest {
func test_UISearchBarDelegateExtension() {
performDelegateTest(UISearchBarSubclass(frame: CGRect.zero))
}
}
#endif
// MARK: UITextView
extension DelegateProxyTest {
@ -254,6 +272,38 @@ class UIScrollViewSubclass
}
}
#if os(iOS)
class ExtendSearchBarDelegateProxy
: RxSearchBarDelegateProxy
, UISearchBarDelegateSubclass {
weak private(set) var control: UISearchBarSubclass?
required init(parentObject: AnyObject) {
self.control = (parentObject as! UISearchBarSubclass)
super.init(parentObject: parentObject)
}
}
class UISearchBarSubclass
: UISearchBar
, TestDelegateControl {
override func rx_createDelegateProxy() -> RxSearchBarDelegateProxy {
return ExtendSearchBarDelegateProxy(parentObject: self)
}
func doThatTest(value: Int) {
(delegate as! TestDelegateProtocol).testEventHappened?(value)
}
var test: Observable<Int> {
return rx_delegate
.observe(#selector(TestDelegateProtocol.testEventHappened(_:)))
.map { a in (a[0] as! NSNumber).integerValue }
}
}
#endif
class ExtendTextViewDelegateProxy
: RxTextViewDelegateProxy
, UITextViewDelegateSubclass {

View File

@ -76,4 +76,44 @@ class UISearchBarTests : RxTest {
_ = Observable.just(1).bindTo(searchBar.rx_selectedScopeButtonIndex)
XCTAssertEqual(searchBar.selectedScopeButtonIndex, 1)
}
#if os(iOS)
func testCancelButtonClicked() {
let searchBar = UISearchBar(frame: CGRectMake(0, 0, 1, 1))
var tapped = false
let _ = searchBar.rx_cancelButtonClicked.subscribeNext { _ in
tapped = true
}
XCTAssertFalse(tapped)
searchBar.delegate!.searchBarCancelButtonClicked!(searchBar)
XCTAssertTrue(tapped)
}
func testCancelButtonClicked_DelegateEventCompletesOnDealloc() {
let createView: () -> UISearchBar = { UISearchBar(frame: CGRectMake(0, 0, 1, 1)) }
ensureEventDeallocated(createView) { (view: UISearchBar) in view.rx_cancelButtonClicked }
}
#endif
func testSearchButtonClicked() {
let searchBar = UISearchBar(frame: CGRectMake(0, 0, 1, 1))
var tapped = false
let _ = searchBar.rx_searchButtonClicked.subscribeNext { _ in
tapped = true
}
XCTAssertFalse(tapped)
searchBar.delegate!.searchBarSearchButtonClicked!(searchBar)
XCTAssertTrue(tapped)
}
func testSearchButtonClicked_DelegateEventCompletesOnDealloc() {
let createView: () -> UISearchBar = { UISearchBar(frame: CGRectMake(0, 0, 1, 1)) }
ensureEventDeallocated(createView) { (view: UISearchBar) in view.rx_searchButtonClicked }
}
}