From 39f7ea147517e4fb2c6ebbb1a8594d3b74b5f12d Mon Sep 17 00:00:00 2001 From: persidskiy Date: Wed, 2 Dec 2015 23:08:05 +0300 Subject: [PATCH] Add rx_animating to UIActivityIndicatorView --- CHANGELOG.md | 1 + Documentation/API.md | 8 ++++ Rx.xcodeproj/project.pbxproj | 8 ++++ RxCocoa/iOS/UIActivityIndicatorView+Rx.swift | 42 +++++++++++++++++++ RxExample/RxExample.xcodeproj/project.pbxproj | 4 ++ .../APIWrappersViewController.swift | 8 ++++ RxExample/RxExample/iOS/Main.storyboard | 6 ++- .../RxCocoaTests/Control+RxTests+UIKit.swift | 20 +++++++++ 8 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 RxCocoa/iOS/UIActivityIndicatorView+Rx.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 909dbe1c..171d7faf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. * Adds `ignoreElements` operator. * Adds `rx_attributedText` to `UILabel`. +* Adds `rx_animating` to `UIActivityIndicatorView`. --- diff --git a/Documentation/API.md b/Documentation/API.md index 2b621cc1..491de24d 100644 --- a/Documentation/API.md +++ b/Documentation/API.md @@ -405,6 +405,14 @@ extension UISwitch { } ``` +```swift +extension UIActivityIndicatorView { + + public var rx_animating: AnyObserver {} + +} +``` + **OSX** ```swift diff --git a/Rx.xcodeproj/project.pbxproj b/Rx.xcodeproj/project.pbxproj index b0fd1398..e4b3869a 100644 --- a/Rx.xcodeproj/project.pbxproj +++ b/Rx.xcodeproj/project.pbxproj @@ -7,6 +7,9 @@ objects = { /* Begin PBXBuildFile section */ + 9BA1CBD31C0F7D550044B50A /* UIActivityIndicatorView+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BA1CBD11C0F7C0A0044B50A /* UIActivityIndicatorView+Rx.swift */; }; + 9BA1CBFD1C0F84A10044B50A /* UIActivityIndicatorView+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BA1CBD11C0F7C0A0044B50A /* UIActivityIndicatorView+Rx.swift */; }; + 9BA1CBFE1C0F84C40044B50A /* UIActivityIndicatorView+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BA1CBD11C0F7C0A0044B50A /* UIActivityIndicatorView+Rx.swift */; }; 9D71C4D21BF08191006E8F59 /* UIButton+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = C88254061B8A752B00B02D69 /* UIButton+Rx.swift */; }; B1B7C3BD1BDD39DB0076934E /* TakeLast.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1B7C3BC1BDD39DB0076934E /* TakeLast.swift */; }; B1B7C3BE1BDD39DB0076934E /* TakeLast.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1B7C3BC1BDD39DB0076934E /* TakeLast.swift */; }; @@ -877,6 +880,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 9BA1CBD11C0F7C0A0044B50A /* UIActivityIndicatorView+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIActivityIndicatorView+Rx.swift"; sourceTree = ""; }; A111CE961B91C97C00D0DCEE /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; B1B7C3BC1BDD39DB0076934E /* TakeLast.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TakeLast.swift; sourceTree = ""; }; B1D8998E1BF653410027B05C /* Timeout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Timeout.swift; sourceTree = ""; }; @@ -1558,6 +1562,7 @@ C88254121B8A752B00B02D69 /* UITableView+Rx.swift */, C88254131B8A752B00B02D69 /* UITextField+Rx.swift */, C88254141B8A752B00B02D69 /* UITextView+Rx.swift */, + 9BA1CBD11C0F7C0A0044B50A /* UIActivityIndicatorView+Rx.swift */, ); path = iOS; sourceTree = ""; @@ -2155,6 +2160,7 @@ C882541C1B8A752B00B02D69 /* RxActionSheetDelegateProxy.swift in Sources */, C8093ED51B8A732E0088E94D /* _RXDelegateProxy.m in Sources */, C8093EF51B8A732E0088E94D /* NSObject+Rx.swift in Sources */, + 9BA1CBD31C0F7D550044B50A /* UIActivityIndicatorView+Rx.swift in Sources */, C88254241B8A752B00B02D69 /* RxTextViewDelegateProxy.swift in Sources */, C88254271B8A752B00B02D69 /* UIBarButtonItem+Rx.swift in Sources */, C88254251B8A752B00B02D69 /* UIActionSheet+Rx.swift in Sources */, @@ -2716,6 +2722,7 @@ C8F0C0251BBBFBB9001B112F /* RxActionSheetDelegateProxy.swift in Sources */, C8F0C0261BBBFBB9001B112F /* _RXDelegateProxy.m in Sources */, C8F0C0271BBBFBB9001B112F /* NSObject+Rx.swift in Sources */, + 9BA1CBFE1C0F84C40044B50A /* UIActivityIndicatorView+Rx.swift in Sources */, C8F0C0281BBBFBB9001B112F /* RxTextViewDelegateProxy.swift in Sources */, C8F0C0291BBBFBB9001B112F /* UIBarButtonItem+Rx.swift in Sources */, C8F0C02A1BBBFBB9001B112F /* UIActionSheet+Rx.swift in Sources */, @@ -2802,6 +2809,7 @@ D2138C961BB9BEDA00339B5C /* NSURLSession+Rx.swift in Sources */, D203C5051BB9C53E00D02D00 /* UICollectionView+Rx.swift in Sources */, D2138C8D1BB9BECD00339B5C /* ControlProperty.swift in Sources */, + 9BA1CBFD1C0F84A10044B50A /* UIActivityIndicatorView+Rx.swift in Sources */, D203C5071BB9C53E00D02D00 /* UIDatePicker+Rx.swift in Sources */, D2138C941BB9BEDA00339B5C /* NSObject+Rx+CoreGraphics.swift in Sources */, D203C50D1BB9C53E00D02D00 /* UISegmentedControl+Rx.swift in Sources */, diff --git a/RxCocoa/iOS/UIActivityIndicatorView+Rx.swift b/RxCocoa/iOS/UIActivityIndicatorView+Rx.swift new file mode 100644 index 00000000..0c97b220 --- /dev/null +++ b/RxCocoa/iOS/UIActivityIndicatorView+Rx.swift @@ -0,0 +1,42 @@ +// +// UIActivityIndicatorView+Rx.swift +// Rx +// +// Created by Ivan Persidskiy on 02/12/15. +// Copyright © 2015 Krunoslav Zaher. All rights reserved. +// + +#if os(iOS) || os(tvOS) +import UIKit + +#if !RX_NO_MODULE +import RxSwift +#endif + +extension UIActivityIndicatorView { + + /* + Bindable sink for `startAnimating()`, `stopAnimating()` methods. + */ + public var rx_animating: AnyObserver { + return AnyObserver {event in + MainScheduler.ensureExecutingOnScheduler() + + switch (event) { + case .Next(let value): + if value { + self.startAnimating() + } else { + self.stopAnimating() + } + case .Error(let error): + bindingErrorToInterface(error) + case .Completed: + break + } + } + } + +} + +#endif diff --git a/RxExample/RxExample.xcodeproj/project.pbxproj b/RxExample/RxExample.xcodeproj/project.pbxproj index 951abf56..51b8a653 100644 --- a/RxExample/RxExample.xcodeproj/project.pbxproj +++ b/RxExample/RxExample.xcodeproj/project.pbxproj @@ -17,6 +17,7 @@ 07E300071B14995F00F00100 /* TableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07E300061B14995F00F00100 /* TableViewController.swift */; }; 07E300091B149A2A00F00100 /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07E300081B149A2A00F00100 /* User.swift */; }; 07E3C2331B03605B0010338D /* Dependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07E3C2321B03605B0010338D /* Dependencies.swift */; }; + 9B4612951C106CF100BBBB4E /* UIActivityIndicatorView+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B4612941C106CF100BBBB4E /* UIActivityIndicatorView+Rx.swift */; }; B1604CB51BE49F8D002E1279 /* DownloadableImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1604CB41BE49F8D002E1279 /* DownloadableImage.swift */; }; B1604CC21BE5B895002E1279 /* ReachabilityService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B18F3BE11BDB2E8F000AAC79 /* ReachabilityService.swift */; }; B1604CC31BE5B8BD002E1279 /* ReachabilityService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B18F3BE11BDB2E8F000AAC79 /* ReachabilityService.swift */; }; @@ -499,6 +500,7 @@ 07E300061B14995F00F00100 /* TableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewController.swift; sourceTree = ""; }; 07E300081B149A2A00F00100 /* User.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; }; 07E3C2321B03605B0010338D /* Dependencies.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Dependencies.swift; path = Examples/Dependencies.swift; sourceTree = ""; }; + 9B4612941C106CF100BBBB4E /* UIActivityIndicatorView+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIActivityIndicatorView+Rx.swift"; sourceTree = ""; }; B1604CB41BE49F8D002E1279 /* DownloadableImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownloadableImage.swift; sourceTree = ""; }; B1604CC81BE5BBFA002E1279 /* UIImageView+DownloadableImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImageView+DownloadableImage.swift"; sourceTree = ""; }; B18F3BBB1BD92EC8000AAC79 /* Reachability.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Reachability.swift; sourceTree = ""; }; @@ -1396,6 +1398,7 @@ C89465571BC6C2BC0055219D /* UITableView+Rx.swift */, C89465581BC6C2BC0055219D /* UITextField+Rx.swift */, C89465591BC6C2BC0055219D /* UITextView+Rx.swift */, + 9B4612941C106CF100BBBB4E /* UIActivityIndicatorView+Rx.swift */, ); path = iOS; sourceTree = ""; @@ -1715,6 +1718,7 @@ files = ( C84CC58B1BDD486300E06A64 /* LockOwnerType.swift in Sources */, C89465971BC6C2BC0055219D /* UIScrollView+Rx.swift in Sources */, + 9B4612951C106CF100BBBB4E /* UIActivityIndicatorView+Rx.swift in Sources */, C8297E2F1B6CF905000589EA /* RxTableViewSectionedAnimatedDataSource.swift in Sources */, C89464D41BC6C2B00055219D /* ObserveOn.swift in Sources */, C894659B1BC6C2BC0055219D /* UIStepper+Rx.swift in Sources */, diff --git a/RxExample/RxExample/Examples/APIWrappers/APIWrappersViewController.swift b/RxExample/RxExample/Examples/APIWrappers/APIWrappersViewController.swift index 4e81e939..479940ca 100644 --- a/RxExample/RxExample/Examples/APIWrappers/APIWrappersViewController.swift +++ b/RxExample/RxExample/Examples/APIWrappers/APIWrappersViewController.swift @@ -39,6 +39,8 @@ class APIWrappersViewController: ViewController { @IBOutlet weak var switcher: UISwitch! + @IBOutlet weak var activityIndicator: UIActivityIndicatorView! + @IBOutlet weak var button: UIButton! @IBOutlet weak var slider: UISlider! @@ -145,6 +147,12 @@ class APIWrappersViewController: ViewController { } .addDisposableTo(disposeBag) + // MARK: UIActivityIndicatorView + + switcher.rx_value + .bindTo(activityIndicator.rx_animating) + .addDisposableTo(disposeBag) + // MARK: UIButton diff --git a/RxExample/RxExample/iOS/Main.storyboard b/RxExample/RxExample/iOS/Main.storyboard index e2290561..343a7ada 100644 --- a/RxExample/RxExample/iOS/Main.storyboard +++ b/RxExample/RxExample/iOS/Main.storyboard @@ -1,5 +1,5 @@ - + @@ -817,6 +817,9 @@ This is only showcase app, not intended for production purposes. + @@ -831,6 +834,7 @@ This is only showcase app, not intended for production purposes. + diff --git a/RxTests/RxCocoaTests/Control+RxTests+UIKit.swift b/RxTests/RxCocoaTests/Control+RxTests+UIKit.swift index 097f7e0c..b502e7e9 100644 --- a/RxTests/RxCocoaTests/Control+RxTests+UIKit.swift +++ b/RxTests/RxCocoaTests/Control+RxTests+UIKit.swift @@ -313,6 +313,26 @@ extension ControlTests { } } +// UIActivityIndicatorView +extension ControlTests { + func testActivityIndicator_HasWeakReference() { + ensureControlObserverHasWeakReference(UIActivityIndicatorView(), { (view: UIActivityIndicatorView) -> AnyObserver in view.rx_animating }, { Variable(true).asObservable() }) + } + + func testActivityIndicator_NextElementsSetsValue() { + let subject = UIActivityIndicatorView() + let boolSequence = Variable(false) + + boolSequence.subscribe(subject.rx_animating) + + boolSequence.value = true + XCTAssertTrue(subject.isAnimating(), "Expected animation to be started") + + boolSequence.value = false + XCTAssertFalse(subject.isAnimating(), "Expected animation to be stopped") + } +} + #if os(iOS)