From db95d13cfd7163890cf8e6aa951a999eb48c1c3f Mon Sep 17 00:00:00 2001 From: Andrew Breckenridge Date: Tue, 30 Aug 2016 10:34:11 -0700 Subject: [PATCH 1/9] create UIWebView+Rx.swift --- Rx.xcodeproj/project.pbxproj | 4 +++ RxCocoa/iOS/UIAlertAction+Rx.swift | 2 -- RxCocoa/iOS/UIWebView+Rx.swift | 55 ++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 RxCocoa/iOS/UIWebView+Rx.swift diff --git a/Rx.xcodeproj/project.pbxproj b/Rx.xcodeproj/project.pbxproj index 6d5b7b85..3ddd8265 100644 --- a/Rx.xcodeproj/project.pbxproj +++ b/Rx.xcodeproj/project.pbxproj @@ -18,6 +18,7 @@ 271A97441CFC9F7B00D64125 /* UIViewControler+RxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271A97421CFC99FE00D64125 /* UIViewControler+RxTests.swift */; }; 46307D4E1CDE77D800E47A1C /* UIAlertAction+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46307D4D1CDE77D800E47A1C /* UIAlertAction+Rx.swift */; }; 46307D4F1CDE77D800E47A1C /* UIAlertAction+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46307D4D1CDE77D800E47A1C /* UIAlertAction+Rx.swift */; }; + 46D3EE251D75F921006F337B /* UIWebView+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D3EE231D75F8D2006F337B /* UIWebView+Rx.swift */; }; 54700CA01CE37E1800EF3A8F /* UINavigationItem+RxTests.swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54700C9E1CE37D1000EF3A8F /* UINavigationItem+RxTests.swift.swift */; }; 54700CA11CE37E1900EF3A8F /* UINavigationItem+RxTests.swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54700C9E1CE37D1000EF3A8F /* UINavigationItem+RxTests.swift.swift */; }; 54D2138E1CE0824E0028D5B4 /* UINavigationItem+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D2138C1CE081890028D5B4 /* UINavigationItem+Rx.swift */; }; @@ -1424,6 +1425,7 @@ 271A97401CFC996B00D64125 /* UIViewController+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+Rx.swift"; sourceTree = ""; }; 271A97421CFC99FE00D64125 /* UIViewControler+RxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewControler+RxTests.swift"; sourceTree = ""; }; 46307D4D1CDE77D800E47A1C /* UIAlertAction+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIAlertAction+Rx.swift"; sourceTree = ""; }; + 46D3EE231D75F8D2006F337B /* UIWebView+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIWebView+Rx.swift"; sourceTree = ""; }; 54700C9E1CE37D1000EF3A8F /* UINavigationItem+RxTests.swift.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UINavigationItem+RxTests.swift.swift"; sourceTree = ""; }; 54D2138C1CE081890028D5B4 /* UINavigationItem+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UINavigationItem+Rx.swift"; sourceTree = ""; }; 7EDBAEAB1C89B1A5006CBE67 /* UITabBarItem+RxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UITabBarItem+RxTests.swift"; sourceTree = ""; }; @@ -2498,6 +2500,7 @@ 54D2138C1CE081890028D5B4 /* UINavigationItem+Rx.swift */, 844BC8B31CE4FD7500F5C7CB /* UIPickerView+Rx.swift */, 46307D4D1CDE77D800E47A1C /* UIAlertAction+Rx.swift */, + 46D3EE231D75F8D2006F337B /* UIWebView+Rx.swift */, ); path = iOS; sourceTree = ""; @@ -3521,6 +3524,7 @@ C89AB1D61DAAC3350065FBE6 /* Driver+Subscription.swift in Sources */, 54D2138E1CE0824E0028D5B4 /* UINavigationItem+Rx.swift in Sources */, 91BE429C1CBF7EC000F6B062 /* UIPageControl+Rx.swift in Sources */, + 46D3EE251D75F921006F337B /* UIWebView+Rx.swift in Sources */, C88254211B8A752B00B02D69 /* RxSearchBarDelegateProxy.swift in Sources */, 7EDBAEBC1C89B9B7006CBE67 /* UITabBarItem+Rx.swift in Sources */, C839365F1C70E02200A9A09E /* UIApplication+Rx.swift in Sources */, diff --git a/RxCocoa/iOS/UIAlertAction+Rx.swift b/RxCocoa/iOS/UIAlertAction+Rx.swift index 2a743014..1fba38f1 100644 --- a/RxCocoa/iOS/UIAlertAction+Rx.swift +++ b/RxCocoa/iOS/UIAlertAction+Rx.swift @@ -6,8 +6,6 @@ // Copyright © 2016 Krunoslav Zaher. All rights reserved. // -import Foundation - #if os(iOS) || os(tvOS) import Foundation diff --git a/RxCocoa/iOS/UIWebView+Rx.swift b/RxCocoa/iOS/UIWebView+Rx.swift new file mode 100644 index 00000000..f03d7365 --- /dev/null +++ b/RxCocoa/iOS/UIWebView+Rx.swift @@ -0,0 +1,55 @@ +// +// UIWebView+Rx.swift +// Rx +// +// Created by Andrew Breckenridge on 8/30/16. +// Copyright © 2016 Krunoslav Zaher. All rights reserved. +// + +#if os(iOS) + +import Foundation +import UIKit + +#if !RX_NO_MODULE +import RxSwift +#endif + +extension Reactive where Base: UIWebView { + + /** + Reactive wrapper for `delegate`. + For more information take a look at `DelegateProxyType` protocol documentation. + */ + public var delegate: DelegateProxy { + return RxSearchControllerDelegateProxy.proxyForObject(base) + } + /** + Reactive wrapper for `delegate` message. + */ + public var didStartLoad: Observable { + return delegate + .methodInvoked(#selector(UIWebViewDelegate.webViewDidStartLoad(_:))) + .map {_ in} + } + /** + Reactive wrapper for `delegate` message. + */ + public var didFinishLoad: Observable { + return delegate + .methodInvoked(#selector(UIWebViewDelegate.webViewDidFinishLoad(_:))) + .map {_ in} + } + /** + Reactive wrapper for `delegate` message. + */ + public var didFailLoad: Observable { + return delegate + .methodInvoked(#selector(UIWebViewDelegate.webView(_:didFailLoadWithError:))) + .map { a in + return try castOrThrow(Error.self, a[1]) + } + } +} + +#endif From 241517403f5d78118f150639aac6831a1dbdae6a Mon Sep 17 00:00:00 2001 From: Andrew Breckenridge Date: Tue, 30 Aug 2016 10:53:22 -0700 Subject: [PATCH 2/9] create UIWebView+RxTests --- Rx.xcodeproj/project.pbxproj | 13 ++-- Tests/RxCocoaTests/UIWebView+RxTests.swift | 74 ++++++++++++++++++++++ 2 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 Tests/RxCocoaTests/UIWebView+RxTests.swift diff --git a/Rx.xcodeproj/project.pbxproj b/Rx.xcodeproj/project.pbxproj index 3ddd8265..a6fde554 100644 --- a/Rx.xcodeproj/project.pbxproj +++ b/Rx.xcodeproj/project.pbxproj @@ -16,9 +16,10 @@ 1AF67DA81CED430100C310FA /* ReplaySubjectTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AF67DA51CED430100C310FA /* ReplaySubjectTest.swift */; }; 271A97411CFC996B00D64125 /* UIViewController+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271A97401CFC996B00D64125 /* UIViewController+Rx.swift */; }; 271A97441CFC9F7B00D64125 /* UIViewControler+RxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271A97421CFC99FE00D64125 /* UIViewControler+RxTests.swift */; }; + 4613456F1D9A4467001ABAF2 /* UIWebView+RxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4613456E1D9A4467001ABAF2 /* UIWebView+RxTests.swift */; }; + 461345711D9A4543001ABAF2 /* UIWebView+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 461345701D9A4543001ABAF2 /* UIWebView+Rx.swift */; }; 46307D4E1CDE77D800E47A1C /* UIAlertAction+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46307D4D1CDE77D800E47A1C /* UIAlertAction+Rx.swift */; }; 46307D4F1CDE77D800E47A1C /* UIAlertAction+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46307D4D1CDE77D800E47A1C /* UIAlertAction+Rx.swift */; }; - 46D3EE251D75F921006F337B /* UIWebView+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D3EE231D75F8D2006F337B /* UIWebView+Rx.swift */; }; 54700CA01CE37E1800EF3A8F /* UINavigationItem+RxTests.swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54700C9E1CE37D1000EF3A8F /* UINavigationItem+RxTests.swift.swift */; }; 54700CA11CE37E1900EF3A8F /* UINavigationItem+RxTests.swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54700C9E1CE37D1000EF3A8F /* UINavigationItem+RxTests.swift.swift */; }; 54D2138E1CE0824E0028D5B4 /* UINavigationItem+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D2138C1CE081890028D5B4 /* UINavigationItem+Rx.swift */; }; @@ -1424,8 +1425,9 @@ 1AF67DA51CED430100C310FA /* ReplaySubjectTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReplaySubjectTest.swift; sourceTree = ""; }; 271A97401CFC996B00D64125 /* UIViewController+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+Rx.swift"; sourceTree = ""; }; 271A97421CFC99FE00D64125 /* UIViewControler+RxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewControler+RxTests.swift"; sourceTree = ""; }; + 4613456E1D9A4467001ABAF2 /* UIWebView+RxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIWebView+RxTests.swift"; sourceTree = ""; }; + 461345701D9A4543001ABAF2 /* UIWebView+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIWebView+Rx.swift"; sourceTree = ""; }; 46307D4D1CDE77D800E47A1C /* UIAlertAction+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIAlertAction+Rx.swift"; sourceTree = ""; }; - 46D3EE231D75F8D2006F337B /* UIWebView+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIWebView+Rx.swift"; sourceTree = ""; }; 54700C9E1CE37D1000EF3A8F /* UINavigationItem+RxTests.swift.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UINavigationItem+RxTests.swift.swift"; sourceTree = ""; }; 54D2138C1CE081890028D5B4 /* UINavigationItem+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UINavigationItem+Rx.swift"; sourceTree = ""; }; 7EDBAEAB1C89B1A5006CBE67 /* UITabBarItem+RxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UITabBarItem+RxTests.swift"; sourceTree = ""; }; @@ -2297,6 +2299,7 @@ 033C2EF41D081B2A0050C015 /* UIScrollView+RxTests.swift */, C8379EF31D1DD326003EF8FC /* UIButton+RxTests.swift */, C8A9B6F31DAD752200C9B027 /* Observable+BindTests.swift */, + 4613456E1D9A4467001ABAF2 /* UIWebView+RxTests.swift */, ); path = RxCocoaTests; sourceTree = ""; @@ -2500,7 +2503,7 @@ 54D2138C1CE081890028D5B4 /* UINavigationItem+Rx.swift */, 844BC8B31CE4FD7500F5C7CB /* UIPickerView+Rx.swift */, 46307D4D1CDE77D800E47A1C /* UIAlertAction+Rx.swift */, - 46D3EE231D75F8D2006F337B /* UIWebView+Rx.swift */, + 461345701D9A4543001ABAF2 /* UIWebView+Rx.swift */, ); path = iOS; sourceTree = ""; @@ -3492,6 +3495,7 @@ C882542F1B8A752B00B02D69 /* UIScrollView+Rx.swift in Sources */, 844BC8B41CE4FD7500F5C7CB /* UIPickerView+Rx.swift in Sources */, C89AB20E1DAAC3350065FBE6 /* Logging.swift in Sources */, + 461345711D9A4543001ABAF2 /* UIWebView+Rx.swift in Sources */, C8093EE31B8A732E0088E94D /* DelegateProxyType.swift in Sources */, C8093EFD1B8A732E0088E94D /* RxTarget.swift in Sources */, C88254361B8A752B00B02D69 /* UITextView+Rx.swift in Sources */, @@ -3524,7 +3528,6 @@ C89AB1D61DAAC3350065FBE6 /* Driver+Subscription.swift in Sources */, 54D2138E1CE0824E0028D5B4 /* UINavigationItem+Rx.swift in Sources */, 91BE429C1CBF7EC000F6B062 /* UIPageControl+Rx.swift in Sources */, - 46D3EE251D75F921006F337B /* UIWebView+Rx.swift in Sources */, C88254211B8A752B00B02D69 /* RxSearchBarDelegateProxy.swift in Sources */, 7EDBAEBC1C89B9B7006CBE67 /* UITabBarItem+Rx.swift in Sources */, C839365F1C70E02200A9A09E /* UIApplication+Rx.swift in Sources */, @@ -3710,6 +3713,8 @@ C83509651C38706E0027C24C /* VirtualSchedulerTest.swift in Sources */, C83509361C38706E0027C24C /* NSLayoutConstraint+RxTests.swift in Sources */, C835095E1C38706E0027C24C /* Observable+StandardSequenceOperatorsTest.swift in Sources */, + 4613456F1D9A4467001ABAF2 /* UIWebView+RxTests.swift in Sources */, + C83509691C38706E0027C24C /* Recorded+Timeless.swift in Sources */, C835094C1C38706E0027C24C /* AssumptionsTest.swift in Sources */, C835092D1C38706E0027C24C /* Control+RxTests.swift in Sources */, C83509601C38706E0027C24C /* Observable+TimeTest.swift in Sources */, diff --git a/Tests/RxCocoaTests/UIWebView+RxTests.swift b/Tests/RxCocoaTests/UIWebView+RxTests.swift new file mode 100644 index 00000000..5b124ec4 --- /dev/null +++ b/Tests/RxCocoaTests/UIWebView+RxTests.swift @@ -0,0 +1,74 @@ +// +// UIWebView+RxTests.swift +// Rx +// +// Created by Andrew Breckenridge on 8/30/16. +// Copyright © 2016 Krunoslav Zaher. All rights reserved. +// + +#if os(iOS) + +import Foundation +import UIKit +import RxSwift +import RxCocoa +import RxBlocking +import XCTest + +class UIWebViewTests: RxTest {} + +fileprivate let testHTMLString = "

🔥

" + +extension UIWebViewTests { + + func testDidStartLoad() { + let webView = UIWebView() + let expect = expectation(description: "webView did start loading") + + let subscription = webView.rx.didStartLoad.subscribe(onNext: { + expect.fulfill() + }) + + webView.loadHTMLString(testHTMLString, baseURL: nil) + + waitForExpectations(timeout: 1, handler: { error in + XCTAssertNil(error) + subscription.dispose() + }) + } + + func testDidFinishLoad() { + let webView = UIWebView() + let expect = expectation(description: "webView did finish loading") + + let subscription = webView.rx.didFinishLoad.subscribe(onNext: { + expect.fulfill() + }) + + webView.loadHTMLString("", baseURL: nil) + + waitForExpectations(timeout: 1, handler: { error in + XCTAssertNil(error) + subscription.dispose() + }) + } + + func testDidFailLoad() { + let webView = UIWebView() + let expect = expectation(description: "webView did fail load") + + let subscription = webView.rx.didFailLoad.subscribe { _ in + expect.fulfill() + } + + webView.delegate!.webView!(webView, didFailLoadWithError: NSError(domain: "", code: 0, userInfo: .none)) + + waitForExpectations(timeout: 2, handler: { error in + XCTAssertNil(error) + subscription.dispose() + }) + } + +} + +#endif From 5eb53904f00f1ae466b00f164dad8bf64e484b87 Mon Sep 17 00:00:00 2001 From: Andrew Breckenridge Date: Mon, 26 Sep 2016 23:39:32 -0700 Subject: [PATCH 3/9] create RxWebViewDelegateProxy --- Rx.xcodeproj/project.pbxproj | 4 ++ .../iOS/Proxies/RxWebViewDelegateProxy.swift | 40 +++++++++++++++++++ RxCocoa/iOS/UIWebView+Rx.swift | 2 +- .../DelegateProxyTest+UIKit.swift | 36 +++++++++++++++++ 4 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 RxCocoa/iOS/Proxies/RxWebViewDelegateProxy.swift diff --git a/Rx.xcodeproj/project.pbxproj b/Rx.xcodeproj/project.pbxproj index a6fde554..695467b5 100644 --- a/Rx.xcodeproj/project.pbxproj +++ b/Rx.xcodeproj/project.pbxproj @@ -18,6 +18,7 @@ 271A97441CFC9F7B00D64125 /* UIViewControler+RxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271A97421CFC99FE00D64125 /* UIViewControler+RxTests.swift */; }; 4613456F1D9A4467001ABAF2 /* UIWebView+RxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4613456E1D9A4467001ABAF2 /* UIWebView+RxTests.swift */; }; 461345711D9A4543001ABAF2 /* UIWebView+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 461345701D9A4543001ABAF2 /* UIWebView+Rx.swift */; }; + 4613457C1D9A4AEE001ABAF2 /* RxWebViewDelegateProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4613457B1D9A4AEE001ABAF2 /* RxWebViewDelegateProxy.swift */; }; 46307D4E1CDE77D800E47A1C /* UIAlertAction+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46307D4D1CDE77D800E47A1C /* UIAlertAction+Rx.swift */; }; 46307D4F1CDE77D800E47A1C /* UIAlertAction+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46307D4D1CDE77D800E47A1C /* UIAlertAction+Rx.swift */; }; 54700CA01CE37E1800EF3A8F /* UINavigationItem+RxTests.swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54700C9E1CE37D1000EF3A8F /* UINavigationItem+RxTests.swift.swift */; }; @@ -1427,6 +1428,7 @@ 271A97421CFC99FE00D64125 /* UIViewControler+RxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewControler+RxTests.swift"; sourceTree = ""; }; 4613456E1D9A4467001ABAF2 /* UIWebView+RxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIWebView+RxTests.swift"; sourceTree = ""; }; 461345701D9A4543001ABAF2 /* UIWebView+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIWebView+Rx.swift"; sourceTree = ""; }; + 4613457B1D9A4AEE001ABAF2 /* RxWebViewDelegateProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxWebViewDelegateProxy.swift; sourceTree = ""; }; 46307D4D1CDE77D800E47A1C /* UIAlertAction+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIAlertAction+Rx.swift"; sourceTree = ""; }; 54700C9E1CE37D1000EF3A8F /* UINavigationItem+RxTests.swift.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UINavigationItem+RxTests.swift.swift"; sourceTree = ""; }; 54D2138C1CE081890028D5B4 /* UINavigationItem+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UINavigationItem+Rx.swift"; sourceTree = ""; }; @@ -2548,6 +2550,7 @@ 84C225A21C33F00B008724EC /* RxTextStorageDelegateProxy.swift */, 846436E11C9AF64C0035B40D /* RxSearchControllerDelegateProxy.swift */, 844BC8AA1CE4FA5600F5C7CB /* RxPickerViewDelegateProxy.swift */, + 4613457B1D9A4AEE001ABAF2 /* RxWebViewDelegateProxy.swift */, ); path = Proxies; sourceTree = ""; @@ -3571,6 +3574,7 @@ C882541A1B8A752B00B02D69 /* RxCollectionViewDataSourceType.swift in Sources */, C88254351B8A752B00B02D69 /* UITextField+Rx.swift in Sources */, C89AB1FE1DAAC3350065FBE6 /* UIBindingObserver.swift in Sources */, + 4613457C1D9A4AEE001ABAF2 /* RxWebViewDelegateProxy.swift in Sources */, C88254301B8A752B00B02D69 /* UISearchBar+Rx.swift in Sources */, C89AB2121DAAC3350065FBE6 /* NSNotificationCenter+Rx.swift in Sources */, C88254181B8A752B00B02D69 /* ItemEvents.swift in Sources */, diff --git a/RxCocoa/iOS/Proxies/RxWebViewDelegateProxy.swift b/RxCocoa/iOS/Proxies/RxWebViewDelegateProxy.swift new file mode 100644 index 00000000..dac08306 --- /dev/null +++ b/RxCocoa/iOS/Proxies/RxWebViewDelegateProxy.swift @@ -0,0 +1,40 @@ +// +// RxWebViewDelegateProxy.swift +// Rx +// +// Created by Andrew Breckenridge on 9/26/16. +// Copyright © 2016 Krunoslav Zaher. All rights reserved. +// + +#if os(iOS) +import UIKit + +#if !RX_NO_MODULE +import RxSwift +#endif + +public class RxWebViewDelegateProxy + : DelegateProxy + , DelegateProxyType + , UIWebViewDelegate { + + /** + For more information take a look at `DelegateProxyType`. + */ + public class func setCurrentDelegate(_ delegate: AnyObject?, toObject object: AnyObject) { + let webView: UIWebView = castOrFatalError(object) + webView.delegate = castOptionalOrFatalError(delegate) + } + + /** + For more information take a look at `DelegateProxyType`. + */ + public class func currentDelegateFor(_ object: AnyObject) -> AnyObject? { + let webView: UIWebView = castOrFatalError(object) + return webView.delegate + } + + +} + +#endif diff --git a/RxCocoa/iOS/UIWebView+Rx.swift b/RxCocoa/iOS/UIWebView+Rx.swift index f03d7365..6843abd4 100644 --- a/RxCocoa/iOS/UIWebView+Rx.swift +++ b/RxCocoa/iOS/UIWebView+Rx.swift @@ -22,7 +22,7 @@ extension Reactive where Base: UIWebView { For more information take a look at `DelegateProxyType` protocol documentation. */ public var delegate: DelegateProxy { - return RxSearchControllerDelegateProxy.proxyForObject(base) + return RxWebViewDelegateProxy.proxyForObject(base) } /** Reactive wrapper for `delegate` message. diff --git a/Tests/RxCocoaTests/DelegateProxyTest+UIKit.swift b/Tests/RxCocoaTests/DelegateProxyTest+UIKit.swift index 8fcdc108..86f1e8f7 100644 --- a/Tests/RxCocoaTests/DelegateProxyTest+UIKit.swift +++ b/Tests/RxCocoaTests/DelegateProxyTest+UIKit.swift @@ -62,6 +62,7 @@ extension RxSearchControllerDelegateProxy: TestDelegateProtocol { } extension RxPickerViewDelegateProxy: TestDelegateProtocol { } +extension RxWebViewDelegateProxy: TestDelegateProtocol {} #endif // MARK: Tests @@ -133,6 +134,16 @@ extension DelegateProxyTest { } } #endif + +// MARK: UIWebView +#if os(iOS) +extension DelegateProxyTest { + func test_UIWebViewDelegateExtension() { + performDelegateTest(UIWebViewSubclass(frame: CGRect.zero)) + } +} +#endif + // MARK: Mocks class ExtendTableViewDelegateProxy @@ -463,5 +474,30 @@ class UIPickerViewSubclass onProxyForObject: self) } } + +class UIWebViewSubclass: UIWebView, TestDelegateControl { + + func doThatTest(_ value: Int) { + (delegate as! TestDelegateProtocol).testEventHappened?(value) + } + + var testSentMessage: Observable { + return rx.delegate + .sentMessage(#selector(TestDelegateProtocol.testEventHappened(_:))) + .map { a in (a[0] as! NSNumber).intValue } + } + var testMethodInvoked: Observable { + return rx.delegate + .methodInvoked(#selector(TestDelegateProtocol.testEventHappened(_:))) + .map { a in (a[0] as! NSNumber).intValue } + } + + func setMineForwardDelegate(_ testDelegate: TestDelegateProtocol) -> Disposable { + return RxWebViewDelegateProxy.installForwardDelegate(testDelegate, + retainDelegate: false, + onProxyForObject: self) + } +} + #endif From e51d6b7f20178ed63b4d9a459168a827bd1524c4 Mon Sep 17 00:00:00 2001 From: Andrew Breckenridge Date: Tue, 30 Aug 2016 15:19:14 -0700 Subject: [PATCH 4/9] add UIWebView extension CHANGELOG entry --- .jazzy.yml | 2 ++ CHANGELOG.md | 6 ++++++ RxCocoa/iOS/Proxies/RxWebViewDelegateProxy.swift | 2 +- RxCocoa/iOS/UIWebView+Rx.swift | 2 +- Sources/RxCocoa/RxWebViewDelegateProxy.swift | 1 + Sources/RxCocoa/UIWebView+Rx.swift | 1 + Tests/RxCocoaTests/UIWebView+RxTests.swift | 2 +- 7 files changed, 13 insertions(+), 3 deletions(-) create mode 120000 Sources/RxCocoa/RxWebViewDelegateProxy.swift create mode 120000 Sources/RxCocoa/UIWebView+Rx.swift diff --git a/.jazzy.yml b/.jazzy.yml index 901297d0..00ebffc4 100644 --- a/.jazzy.yml +++ b/.jazzy.yml @@ -249,6 +249,7 @@ custom_categories: - UITextView+Rx - UIView+Rx - UIViewController+Rx + - UIWebView+Rx - name: RxCocoa/iOS/Protocols children: - RxCollectionViewDataSourceType @@ -266,6 +267,7 @@ custom_categories: - RxTableViewDelegateProxy - RxTextStorageDelegateProxy - RxTextViewDelegateProxy + - RxWebViewDelegateProxy - name: RxCocoa/macOS children: - NSButton+Rx diff --git a/CHANGELOG.md b/CHANGELOG.md index 96b44a75..cb49731d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file. ## Master +* adds `UIWebView` extensions: + * `didStartLoad` + * `didFinishLoad` + * `didFailLoad` + ## [3.0.1](https://github.com/ReactiveX/RxSwift/releases/tag/3.0.1) (Xcode 8 / Swift 3.0 compatible) #### Anomalies @@ -141,6 +146,7 @@ any observers or `forwardToDelegate` wasn't implementing `UITableViewDataSource. * `textDidEndEditing` * Moves `CLLocationManager` and `UIImagePickerViewController` extensions from RxCocoa to RxExample project. #874 * Adds matrix CI builds. +======= ## [3.0.0.alpha.1](https://github.com/ReactiveX/RxSwift/releases/tag/3.0.0.alpha.1) (Xcode 8 beta 6 compatible 8S201h) diff --git a/RxCocoa/iOS/Proxies/RxWebViewDelegateProxy.swift b/RxCocoa/iOS/Proxies/RxWebViewDelegateProxy.swift index dac08306..fa2b7b40 100644 --- a/RxCocoa/iOS/Proxies/RxWebViewDelegateProxy.swift +++ b/RxCocoa/iOS/Proxies/RxWebViewDelegateProxy.swift @@ -1,6 +1,6 @@ // // RxWebViewDelegateProxy.swift -// Rx +// RxCocoa // // Created by Andrew Breckenridge on 9/26/16. // Copyright © 2016 Krunoslav Zaher. All rights reserved. diff --git a/RxCocoa/iOS/UIWebView+Rx.swift b/RxCocoa/iOS/UIWebView+Rx.swift index 6843abd4..78a0b677 100644 --- a/RxCocoa/iOS/UIWebView+Rx.swift +++ b/RxCocoa/iOS/UIWebView+Rx.swift @@ -1,6 +1,6 @@ // // UIWebView+Rx.swift -// Rx +// RxCocoa // // Created by Andrew Breckenridge on 8/30/16. // Copyright © 2016 Krunoslav Zaher. All rights reserved. diff --git a/Sources/RxCocoa/RxWebViewDelegateProxy.swift b/Sources/RxCocoa/RxWebViewDelegateProxy.swift new file mode 120000 index 00000000..6de07377 --- /dev/null +++ b/Sources/RxCocoa/RxWebViewDelegateProxy.swift @@ -0,0 +1 @@ +../../RxCocoa/iOS/Proxies/RxWebViewDelegateProxy.swift \ No newline at end of file diff --git a/Sources/RxCocoa/UIWebView+Rx.swift b/Sources/RxCocoa/UIWebView+Rx.swift new file mode 120000 index 00000000..80898655 --- /dev/null +++ b/Sources/RxCocoa/UIWebView+Rx.swift @@ -0,0 +1 @@ +../../RxCocoa/iOS/UIWebView+Rx.swift \ No newline at end of file diff --git a/Tests/RxCocoaTests/UIWebView+RxTests.swift b/Tests/RxCocoaTests/UIWebView+RxTests.swift index 5b124ec4..0c49252c 100644 --- a/Tests/RxCocoaTests/UIWebView+RxTests.swift +++ b/Tests/RxCocoaTests/UIWebView+RxTests.swift @@ -1,6 +1,6 @@ // // UIWebView+RxTests.swift -// Rx +// Tests // // Created by Andrew Breckenridge on 8/30/16. // Copyright © 2016 Krunoslav Zaher. All rights reserved. From 5d94c667de4b02d449c716822289f9be0c273c1a Mon Sep 17 00:00:00 2001 From: Andrew Breckenridge Date: Tue, 15 Nov 2016 18:12:25 -0800 Subject: [PATCH 5/9] remove asynchronicity from UIWebView+RxTests --- Tests/RxCocoaTests/UIWebView+RxTests.swift | 36 +++++++++------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/Tests/RxCocoaTests/UIWebView+RxTests.swift b/Tests/RxCocoaTests/UIWebView+RxTests.swift index 0c49252c..aaaf4d38 100644 --- a/Tests/RxCocoaTests/UIWebView+RxTests.swift +++ b/Tests/RxCocoaTests/UIWebView+RxTests.swift @@ -23,52 +23,46 @@ extension UIWebViewTests { func testDidStartLoad() { let webView = UIWebView() - let expect = expectation(description: "webView did start loading") + var didStartLoad = false let subscription = webView.rx.didStartLoad.subscribe(onNext: { - expect.fulfill() + didStartLoad = true }) - webView.loadHTMLString(testHTMLString, baseURL: nil) + webView.delegate!.webViewDidStartLoad!(webView) - waitForExpectations(timeout: 1, handler: { error in - XCTAssertNil(error) - subscription.dispose() - }) + XCTAssertTrue(didStartLoad) + subscription.dispose() } func testDidFinishLoad() { let webView = UIWebView() - let expect = expectation(description: "webView did finish loading") + var didFinishLoad = false let subscription = webView.rx.didFinishLoad.subscribe(onNext: { - expect.fulfill() + didFinishLoad = true }) - webView.loadHTMLString("", baseURL: nil) + webView.delegate!.webViewDidFinishLoad!(webView) - waitForExpectations(timeout: 1, handler: { error in - XCTAssertNil(error) - subscription.dispose() - }) + XCTAssertTrue(didFinishLoad) + subscription.dispose() } func testDidFailLoad() { let webView = UIWebView() - let expect = expectation(description: "webView did fail load") + var didFailLoad = false let subscription = webView.rx.didFailLoad.subscribe { _ in - expect.fulfill() + didFailLoad = true } webView.delegate!.webView!(webView, didFailLoadWithError: NSError(domain: "", code: 0, userInfo: .none)) - waitForExpectations(timeout: 2, handler: { error in - XCTAssertNil(error) - subscription.dispose() - }) + XCTAssertTrue(didFailLoad) + subscription.dispose() } - + } #endif From 3293a6cb6ab8c6437202d4c654ab784a825bb8a2 Mon Sep 17 00:00:00 2001 From: Czajnikowski Date: Sat, 26 Nov 2016 17:51:16 +0100 Subject: [PATCH 6/9] Improve naming in GeolocationViewController Move noGeolocationView into scene dock in storyboard --- .../GeolocationExample/Geolocation.storyboard | 99 ++++++++++--------- .../GeolocationViewController.swift | 27 +++-- 2 files changed, 63 insertions(+), 63 deletions(-) diff --git a/RxExample/RxExample/Examples/GeolocationExample/Geolocation.storyboard b/RxExample/RxExample/Examples/GeolocationExample/Geolocation.storyboard index 60214d8b..ae713d5d 100644 --- a/RxExample/RxExample/Examples/GeolocationExample/Geolocation.storyboard +++ b/RxExample/RxExample/Examples/GeolocationExample/Geolocation.storyboard @@ -1,6 +1,10 @@ + + + + @@ -14,53 +18,9 @@ - + - - - - - - - - - - - - - - - - - - @@ -122,14 +82,10 @@ - - - - @@ -143,6 +99,51 @@ + + + + + + + + + + + + + + + + + + + diff --git a/RxExample/RxExample/Examples/GeolocationExample/GeolocationViewController.swift b/RxExample/RxExample/Examples/GeolocationExample/GeolocationViewController.swift index 211b0f2f..a1066d0a 100644 --- a/RxExample/RxExample/Examples/GeolocationExample/GeolocationViewController.swift +++ b/RxExample/RxExample/Examples/GeolocationExample/GeolocationViewController.swift @@ -14,7 +14,7 @@ import CoreLocation #endif private extension Reactive where Base: UILabel { - var driveCoordinates: UIBindingObserver { + var coordinates: UIBindingObserver { return UIBindingObserver(UIElement: base) { label, location in label.text = "Lat: \(location.latitude)\nLon: \(location.longitude)" } @@ -22,15 +22,13 @@ private extension Reactive where Base: UILabel { } private extension Reactive where Base: UIView { - var driveAuthorization: UIBindingObserver { - return UIBindingObserver(UIElement: base) { view, authorized in - if authorized { - view.isHidden = true - view.superview?.sendSubview(toBack:view) + func subviewPresence(_ subview: UIView) -> UIBindingObserver { + return UIBindingObserver(UIElement: base) { view, show in + if !show { + subview.removeFromSuperview() } else { - view.isHidden = false - view.superview?.bringSubview(toFront:view) + view.addSubview(subview) } } } @@ -42,20 +40,21 @@ class GeolocationViewController: ViewController { @IBOutlet weak private var button: UIButton! @IBOutlet weak private var button2: UIButton! @IBOutlet weak var label: UILabel! - + override func viewDidLoad() { super.viewDidLoad() let geolocationService = GeolocationService.instance - + geolocationService.authorized - .drive(noGeolocationView.rx.driveAuthorization) + .map(!) + .drive(view.rx.subviewPresence(noGeolocationView)) .addDisposableTo(disposeBag) geolocationService.location - .drive(label.rx.driveCoordinates) + .drive(label.rx.coordinates) .addDisposableTo(disposeBag) - + button.rx.tap .bindNext { [weak self] in self?.openAppPreferences() @@ -72,5 +71,5 @@ class GeolocationViewController: ViewController { private func openAppPreferences() { UIApplication.shared.openURL(URL(string: UIApplicationOpenSettingsURLString)!) } - + } From 9cb919ba6ff8fcad63b4bbf915908d61e6c4857a Mon Sep 17 00:00:00 2001 From: Cezary Kopacz Date: Sun, 16 Oct 2016 11:58:51 +0200 Subject: [PATCH 7/9] Added bindable sink for 'title' property --- RxCocoa/iOS/UIBarButtonItem+Rx.swift | 9 +++++++++ Tests/RxCocoaTests/UIBarButtonItem+RxTests.swift | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/RxCocoa/iOS/UIBarButtonItem+Rx.swift b/RxCocoa/iOS/UIBarButtonItem+Rx.swift index e25e3e6d..c10c3cf6 100644 --- a/RxCocoa/iOS/UIBarButtonItem+Rx.swift +++ b/RxCocoa/iOS/UIBarButtonItem+Rx.swift @@ -23,6 +23,15 @@ extension Reactive where Base: UIBarButtonItem { UIElement.isEnabled = value } } + + /** + Bindable sink for `title` property. + */ + public var title: UIBindingObserver { + return UIBindingObserver(UIElement: self.base) { UIElement, value in + UIElement.title = value + } + } /// Reactive wrapper for target action pattern on `self`. public var tap: ControlEvent { diff --git a/Tests/RxCocoaTests/UIBarButtonItem+RxTests.swift b/Tests/RxCocoaTests/UIBarButtonItem+RxTests.swift index d053598a..721ad94b 100644 --- a/Tests/RxCocoaTests/UIBarButtonItem+RxTests.swift +++ b/Tests/RxCocoaTests/UIBarButtonItem+RxTests.swift @@ -21,4 +21,13 @@ extension UIBarButtonItemTests { func testBarButtonItem_DelegateEventCompletesOnDealloc() { ensureEventDeallocated({ UIBarButtonItem() }) { (view: UIBarButtonItem) in view.rx.tap } } + + func testButton_titleObserver() { + let button = UIBarButtonItem() + XCTAssertEqual(button.title, nil) + let text = "title" + _ = Observable.just(text).bindTo(button.rx.title) + + XCTAssertEqual(button.title, text) + } } From 0e1b43af1af2a1da6e58c4db9a88c2a78504fd59 Mon Sep 17 00:00:00 2001 From: Czajnikowski Date: Wed, 7 Dec 2016 18:04:43 +0100 Subject: [PATCH 8/9] Simplify binding in GeolocationViewController Remove warning in Storyboard --- .../GeolocationExample/Geolocation.storyboard | 3 +-- .../GeolocationViewController.swift | 18 +++--------------- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/RxExample/RxExample/Examples/GeolocationExample/Geolocation.storyboard b/RxExample/RxExample/Examples/GeolocationExample/Geolocation.storyboard index ae713d5d..512b47d2 100644 --- a/RxExample/RxExample/Examples/GeolocationExample/Geolocation.storyboard +++ b/RxExample/RxExample/Examples/GeolocationExample/Geolocation.storyboard @@ -95,7 +95,6 @@ - @@ -104,7 +103,7 @@