diff --git a/RxCocoa/RxCocoa.xcodeproj/project.pbxproj b/RxCocoa/RxCocoa.xcodeproj/project.pbxproj index 81af8cf4..0da266c0 100644 --- a/RxCocoa/RxCocoa.xcodeproj/project.pbxproj +++ b/RxCocoa/RxCocoa.xcodeproj/project.pbxproj @@ -27,7 +27,7 @@ C83111711B491C9F001F3D67 /* KVOObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C83111701B491C9F001F3D67 /* KVOObservable.swift */; }; C83111721B491C9F001F3D67 /* KVOObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C83111701B491C9F001F3D67 /* KVOObservable.swift */; }; C83225451B1A9ACC0048EC77 /* UIBarButtonItem+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = C83225441B1A9ACC0048EC77 /* UIBarButtonItem+Rx.swift */; }; - C83225471B1A9CCB0048EC77 /* UIDatePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = C83225461B1A9CCB0048EC77 /* UIDatePicker.swift */; }; + C83225471B1A9CCB0048EC77 /* UIDatePicker+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = C83225461B1A9CCB0048EC77 /* UIDatePicker+Rx.swift */; }; C83225491B1A9ECC0048EC77 /* NSControl+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = C83225481B1A9ECC0048EC77 /* NSControl+Rx.swift */; }; C83CF8631B3DDD54001359E7 /* RxTableViewReactiveArrayDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = C83CF8621B3DDD54001359E7 /* RxTableViewReactiveArrayDataSource.swift */; }; C84969CA1B47DE1D00E0BDB9 /* RxCollectionViewDataSourceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = C84969C51B47DE1D00E0BDB9 /* RxCollectionViewDataSourceProxy.swift */; }; @@ -97,7 +97,7 @@ C81553E31A98AB4A00C63152 /* RxCocoa.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RxCocoa.h; sourceTree = ""; }; C83111701B491C9F001F3D67 /* KVOObservable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KVOObservable.swift; sourceTree = ""; }; C83225441B1A9ACC0048EC77 /* UIBarButtonItem+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIBarButtonItem+Rx.swift"; sourceTree = ""; }; - C83225461B1A9CCB0048EC77 /* UIDatePicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIDatePicker.swift; sourceTree = ""; }; + C83225461B1A9CCB0048EC77 /* UIDatePicker+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIDatePicker+Rx.swift"; sourceTree = ""; }; C83225481B1A9ECC0048EC77 /* NSControl+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSControl+Rx.swift"; sourceTree = ""; }; C83CF8621B3DDD54001359E7 /* RxTableViewReactiveArrayDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxTableViewReactiveArrayDataSource.swift; sourceTree = ""; }; C84969C51B47DE1D00E0BDB9 /* RxCollectionViewDataSourceProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxCollectionViewDataSourceProxy.swift; sourceTree = ""; }; @@ -275,7 +275,7 @@ C88BB8E01B07F2BE0064D411 /* UIButton+Rx.swift */, C88BB8E11B07F2BE0064D411 /* UICollectionView+Rx.swift */, 653C8BF31B114EB600983087 /* UIControl+Rx.swift */, - C83225461B1A9CCB0048EC77 /* UIDatePicker.swift */, + C83225461B1A9CCB0048EC77 /* UIDatePicker+Rx.swift */, C88BB8E21B07F2BE0064D411 /* UIImageView+Rx.swift */, C88BB8E31B07F2BE0064D411 /* UILabel+Rx.swift */, C88BB8E41B07F2BE0064D411 /* UIScrollView+Rx.swift */, @@ -447,7 +447,7 @@ C862823D1B36037100500DC3 /* NSNotificationCenter+Rx.swift in Sources */, C84969CE1B47DE1D00E0BDB9 /* RxTableViewDelegateProxy.swift in Sources */, C86282501B370C7E00500DC3 /* ItemEvents.swift in Sources */, - C83225471B1A9CCB0048EC77 /* UIDatePicker.swift in Sources */, + C83225471B1A9CCB0048EC77 /* UIDatePicker+Rx.swift in Sources */, C83225451B1A9ACC0048EC77 /* UIBarButtonItem+Rx.swift in Sources */, 075F130C1B4DD100000D7861 /* UISegmentedControl+Rx.swift in Sources */, 075F13001B4DD075000D7861 /* RxAlertViewDelegateProxy.swift in Sources */, diff --git a/RxCocoa/RxCocoa/iOS/CLLocationManager+Rx.swift b/RxCocoa/RxCocoa/iOS/CLLocationManager+Rx.swift index 86158052..32bae41f 100644 --- a/RxCocoa/RxCocoa/iOS/CLLocationManager+Rx.swift +++ b/RxCocoa/RxCocoa/iOS/CLLocationManager+Rx.swift @@ -19,24 +19,24 @@ extension CLLocationManager { // MARK: Responding to Location Events - public var rx_didUpdateLocations: Observable<[AnyObject]> { + public var rx_didUpdateLocations: Observable<[CLLocation]!> { return rx_delegate.observe("locationManager:didUpdateLocations:") >- map { a in - return a[1] as! [AnyObject] + return a[1] as! [CLLocation] } } - public var rx_didFailWithError: Observable { + public var rx_didFailWithError: Observable { return rx_delegate.observe("locationManager:didFailWithError:") >- map { a in - return a[1] as! NSError + return a[1] as? NSError } } - public var rx_didFinishDeferredUpdatesWithError: Observable { + public var rx_didFinishDeferredUpdatesWithError: Observable { return rx_delegate.observe("locationManager:didFinishDeferredUpdatesWithError:") >- map { a in - return a[1] as! NSError + return a[1] as? NSError } } @@ -58,10 +58,10 @@ extension CLLocationManager { // MARK: Responding to Heading Events - public var rx_didUpdateHeading: Observable { + public var rx_didUpdateHeading: Observable { return rx_delegate.observe("locationManager:didUpdateHeading:") >- map { a in - return a[1] as! CLHeading + return a[1] as? CLHeading } } @@ -74,63 +74,63 @@ extension CLLocationManager { // MARK: Responding to Region Events - public var rx_didEnterRegion: Observable { + public var rx_didEnterRegion: Observable { return rx_delegate.observe("locationManager:didEnterRegion:") >- map { a in - return a[1] as! CLRegion + return a[1] as? CLRegion } } - public var rx_didExitRegion: Observable { + public var rx_didExitRegion: Observable { return rx_delegate.observe("locationManager:didExitRegion:") >- map { a in - return a[1] as! CLRegion + return a[1] as? CLRegion } } - public var rx_didDetermineStateForRegion: Observable<(state: CLRegionState, region: CLRegion)> { + public var rx_didDetermineStateForRegion: Observable<(state: CLRegionState, region: CLRegion!)> { return rx_delegate.observe("locationManager:didDetermineState:forRegion:") >- map { a in - return (state: a[1] as! CLRegionState, region: a[2] as! CLRegion) + return (state: a[1] as! CLRegionState, region: a[2] as? CLRegion) } } - public var rx_monitoringDidFailForRegionWithError: Observable<(region: CLRegion, error: NSError)> { + public var rx_monitoringDidFailForRegionWithError: Observable<(region: CLRegion!, error: NSError!)> { return rx_delegate.observe("locationManager:monitoringDidFailForRegion:withError:") >- map { a in - return (region: a[1] as! CLRegion, error: a[2] as! NSError) + return (region: a[1] as? CLRegion, error: a[2] as? NSError) } } - public var rx_didStartMonitoringForRegion: Observable { + public var rx_didStartMonitoringForRegion: Observable { return rx_delegate.observe("locationManager:didStartMonitoringForRegion:") >- map { a in - return a[1] as! CLRegion + return a[1] as? CLRegion } } // MARK: Responding to Ranging Events - public var rx_didRangeBeaconsInRegion: Observable<(beacons: [AnyObject], region: CLBeaconRegion)> { + public var rx_didRangeBeaconsInRegion: Observable<(beacons: [CLBeacon]!, region: CLBeaconRegion!)> { return rx_delegate.observe("locationManager:didRangeBeacons:inRegion:") >- map { a in - return (beacons: a[1] as! [AnyObject], region: a[2] as! CLBeaconRegion) + return (beacons: a[1] as? [CLBeacon], region: a[2] as? CLBeaconRegion) } } - public var rx_rangingBeaconsDidFailForRegionWithError: Observable<(region: CLBeaconRegion, error: NSError)> { + public var rx_rangingBeaconsDidFailForRegionWithError: Observable<(region: CLBeaconRegion!, error: NSError!)> { return rx_delegate.observe("locationManager:rangingBeaconsDidFailForRegion:withError:") >- map { a in - return (region: a[1] as! CLBeaconRegion, error: a[2] as! NSError) + return (region: a[1] as? CLBeaconRegion, error: a[2] as? NSError) } } // MARK: Responding to Visit Events - public var rx_didVisit: Observable { + public var rx_didVisit: Observable { return rx_delegate.observe("locationManager:didVisit:") >- map { a in - return a[1] as! CLVisit + return a[1] as? CLVisit } } diff --git a/RxCocoa/RxCocoa/iOS/UIDatePicker+Rx.swift b/RxCocoa/RxCocoa/iOS/UIDatePicker+Rx.swift new file mode 100644 index 00000000..070f2294 --- /dev/null +++ b/RxCocoa/RxCocoa/iOS/UIDatePicker+Rx.swift @@ -0,0 +1,33 @@ +// +// UIDatePicker.swift +// RxCocoa +// +// Created by Daniel Tartaglia on 5/31/15. +// Modified by Carlos García on 7/9/15. +// Copyright (c) 2015 Krunoslav Zaher. All rights reserved. +// + +import Foundation + +import Foundation +import RxSwift +import UIKit + +extension UIDatePicker { + + public var rx_date: Observable { + return AnonymousObservable { observer in + + sendNext(observer, self.date) + + let controlTarget = ControlTarget(control: self, controlEvents: UIControlEvents.ValueChanged) { control in + sendNext(observer, (control as! UIDatePicker).date) + } + + return AnonymousDisposable { + controlTarget.dispose() + } + } + } + +} \ No newline at end of file diff --git a/RxCocoa/RxCocoa/iOS/UIDatePicker.swift b/RxCocoa/RxCocoa/iOS/UIDatePicker.swift deleted file mode 100644 index 511ac1c4..00000000 --- a/RxCocoa/RxCocoa/iOS/UIDatePicker.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// UIDatePicker.swift -// RxCocoa -// -// Created by Daniel Tartaglia on 5/31/15. -// Copyright (c) 2015 Krunoslav Zaher. All rights reserved. -// - -import Foundation - -import Foundation -import RxSwift -import UIKit - -extension UIDatePicker { - - public var rx_date: Observable { - return rx_value { [weak self] in self?.date ?? NSDate() } - } - -} \ No newline at end of file diff --git a/RxExample/RxExample.xcodeproj/project.pbxproj b/RxExample/RxExample.xcodeproj/project.pbxproj index 2290b602..efd82400 100644 --- a/RxExample/RxExample.xcodeproj/project.pbxproj +++ b/RxExample/RxExample.xcodeproj/project.pbxproj @@ -11,6 +11,7 @@ 0706E19B1B17361100BA2D3A /* UIImageView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0706E19A1B17361100BA2D3A /* UIImageView+Extensions.swift */; }; 0706E19D1B176EE200BA2D3A /* String+extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0706E19C1B176EE200BA2D3A /* String+extensions.swift */; }; 0706E19F1B17703E00BA2D3A /* RandomUserAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0706E19E1B17703E00BA2D3A /* RandomUserAPI.swift */; }; + 075F13101B4E9D5A000D7861 /* APIWrappersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 075F130F1B4E9D5A000D7861 /* APIWrappersViewController.swift */; }; 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 */; }; @@ -110,6 +111,7 @@ 0706E19A1B17361100BA2D3A /* UIImageView+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImageView+Extensions.swift"; sourceTree = ""; }; 0706E19C1B176EE200BA2D3A /* String+extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+extensions.swift"; sourceTree = ""; }; 0706E19E1B17703E00BA2D3A /* RandomUserAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RandomUserAPI.swift; sourceTree = ""; }; + 075F130F1B4E9D5A000D7861 /* APIWrappersViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = APIWrappersViewController.swift; sourceTree = ""; }; 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 = ""; }; @@ -213,14 +215,23 @@ name = UIKitExtensions; sourceTree = ""; }; - 07E300051B14994500F00100 /* 04 TableView */ = { + 075F130E1B4E9D10000D7861 /* 04 APIWrappers */ = { + isa = PBXGroup; + children = ( + 075F130F1B4E9D5A000D7861 /* APIWrappersViewController.swift */, + ); + name = "04 APIWrappers"; + path = APIWrappers; + sourceTree = ""; + }; + 07E300051B14994500F00100 /* 05 TableView */ = { isa = PBXGroup; children = ( 0706E1A01B1770C800BA2D3A /* RandomUserAPI */, 0706E1A11B1770D300BA2D3A /* Controllers */, 0706E1A21B1770E200BA2D3A /* UIKitExtensions */, ); - name = "04 TableView"; + name = "05 TableView"; path = TableView; sourceTree = ""; }; @@ -281,14 +292,14 @@ path = Services; sourceTree = ""; }; - C859B9A21B45C5D900D012D7 /* 05 PartialUpdates */ = { + C859B9A21B45C5D900D012D7 /* 06 PartialUpdates */ = { isa = PBXGroup; children = ( C859B9A31B45C5D900D012D7 /* PartialUpdatesViewController.swift */, C859B9AB1B45CF9100D012D7 /* NumberCell.swift */, C859B9AD1B45CFAB00D012D7 /* NumberSectionView.swift */, ); - name = "05 PartialUpdates"; + name = "06 PartialUpdates"; path = PartialUpdates; sourceTree = ""; }; @@ -298,8 +309,9 @@ C8DF92F41B0B4392009BCF9A /* 01 Introduction */, C86E2F4C1AE5A10900C31024 /* 02 GitHubSignup */, C86E2F301AE5A0CA00C31024 /* 03 WikipediaImageSearch */, - 07E300051B14994500F00100 /* 04 TableView */, - C859B9A21B45C5D900D012D7 /* 05 PartialUpdates */, + 075F130E1B4E9D10000D7861 /* 04 APIWrappers */, + 07E300051B14994500F00100 /* 05 TableView */, + C859B9A21B45C5D900D012D7 /* 06 PartialUpdates */, C8A57F711B40AF4E00D5570A /* 06 CoreData */, ); path = Examples; @@ -554,6 +566,7 @@ C8C46DAA1B47F7110020D71E /* WikipediaSearchCell.swift in Sources */, C890A6581AEBD26B00AFF7E6 /* GitHubSignupViewController.swift in Sources */, C8A57F741B40AF7C00D5570A /* Random.xcdatamodeld in Sources */, + 075F13101B4E9D5A000D7861 /* APIWrappersViewController.swift in Sources */, C88C786F1B3EB0A00061C5AB /* RxTableViewSectionedReloadDataSource.swift in Sources */, C859B9AA1B45CB0900D012D7 /* RxCollectionViewSectionedAnimatedDataSource.swift in Sources */, C83367311AD029AE00C668A7 /* Wireframe.swift in Sources */, diff --git a/RxExample/RxExample/Examples/APIWrappers/APIWrappersViewController.swift b/RxExample/RxExample/Examples/APIWrappers/APIWrappersViewController.swift new file mode 100644 index 00000000..018a3c6b --- /dev/null +++ b/RxExample/RxExample/Examples/APIWrappers/APIWrappersViewController.swift @@ -0,0 +1,189 @@ +// +// APIWrappersViewController.swift +// RxExample +// +// Created by Carlos García on 8/7/15. +// Copyright (c) 2015 Krunoslav Zaher. All rights reserved. +// + +import UIKit +import RxSwift +import RxCocoa +import CoreLocation + +class APIWrappersViewController: UIViewController { + + @IBOutlet weak var bbitem: UIBarButtonItem! + + @IBOutlet weak var segmentedControl: UISegmentedControl! + + @IBOutlet weak var switcher: UISwitch! + + @IBOutlet weak var button: UIButton! + + @IBOutlet weak var slider: UISlider! + + @IBOutlet weak var textField: UITextField! + + @IBOutlet weak var datePicker: UIDatePicker! + + @IBOutlet weak var mypan: UIPanGestureRecognizer! + + let disposeBag = DisposeBag() + + let manager = CLLocationManager() + + override func viewDidLoad() { + super.viewDidLoad() + + let ash = UIActionSheet(title: "Title", delegate: nil, cancelButtonTitle: "Cancel", destructiveButtonTitle: "OK") + let av = UIAlertView(title: "Title", message: "The message", delegate: nil, cancelButtonTitle: "Cancel", otherButtonTitles: "OK", "Two", "Three", "Four", "Five") + + // MARK: UIActionSheet + + ash.rx_clickedButtonAtIndex + >- subscribeNext { x in + println("UIActionSheet clickedButtonAtIndex \(x)") + } + >- disposeBag.addDisposable + + ash.rx_willDismissWithButtonIndex + >- subscribeNext { x in + println("UIActionSheet willDismissWithButtonIndex \(x)") + } + >- disposeBag.addDisposable + + ash.rx_didDismissWithButtonIndex + >- subscribeNext { x in + println("UIActionSheet didDismissWithButtonIndex \(x)") + + av.show() + } + >- disposeBag.addDisposable + + + // MARK: UIAlertView + + av.rx_clickedButtonAtIndex + >- subscribeNext { x in + println("UIAlertView clickedButtonAtIndex \(x)") + } + >- disposeBag.addDisposable + + av.rx_willDismissWithButtonIndex + >- subscribeNext { x in + println("UIAlertView willDismissWithButtonIndex \(x)") + } + >- disposeBag.addDisposable + + av.rx_didDismissWithButtonIndex + >- subscribeNext { x in + println("UIAlertView didDismissWithButtonIndex \(x)") + } + >- disposeBag.addDisposable + + + + + ash.showInView(view) + + + // MARK: UIBarButtonItem + + bbitem.rx_tap + >- subscribeNext { x in + println("UIBarButtonItem Tapped") + } + >- disposeBag.addDisposable + + // MARK: UISegmentedControl + + segmentedControl.rx_value + >- subscribeNext { x in + println("UISegmentedControl value \(x)") + } + >- disposeBag.addDisposable + + + // MARK: UISwitch + + switcher.rx_value + >- subscribeNext { x in + println("UISwitch value \(x)") + } + >- disposeBag.addDisposable + + + // MARK: UIButton + + button.rx_tap + >- subscribeNext { x in + println("UIButton Tapped") + } + >- disposeBag.addDisposable + + + // MARK: UISlider + + slider.rx_value + >- subscribeNext { x in + println("UISlider value \(x)") + } + >- disposeBag.addDisposable + + + // MARK: UIDatePicker + + datePicker.rx_date + >- subscribeNext { x in + println("UIDatePicker date \(x)") + } + >- disposeBag.addDisposable + + + // MARK: UITextField + + textField.rx_text + >- subscribeNext { x in + println("UITextField text \(x)") + self.textField.resignFirstResponder() + } + >- disposeBag.addDisposable + + + // MARK: UIGestureRecognizer + + mypan.rx_event + >- subscribeNext { x in + println("UIGestureRecognizer event \(x)") + } + >- disposeBag.addDisposable + + + // MARK: CLLocationManager + + + manager.requestWhenInUseAuthorization() + + manager.rx_didUpdateLocations + >- subscribeNext { x in + println("rx_didUpdateLocations \(x)") + } + >- disposeBag.addDisposable + + manager.rx_didFailWithError + >- subscribeNext { x in + println("rx_didFailWithError \(x)") + } + >- disposeBag.addDisposable + + + manager.startUpdatingLocation() + + + + } + + +} + diff --git a/RxExample/RxExample/Info-iOS.plist b/RxExample/RxExample/Info-iOS.plist index cc02affe..70ef23e7 100644 --- a/RxExample/RxExample/Info-iOS.plist +++ b/RxExample/RxExample/Info-iOS.plist @@ -22,6 +22,8 @@ 1 LSRequiresIPhoneOS + NSLocationAlwaysUsageDescription + We need location UILaunchStoryboardName LaunchScreen UIMainStoryboardFile diff --git a/RxExample/RxExample/iOS/Main.storyboard b/RxExample/RxExample/iOS/Main.storyboard index 3317be11..61877024 100644 --- a/RxExample/RxExample/iOS/Main.storyboard +++ b/RxExample/RxExample/iOS/Main.storyboard @@ -63,7 +63,7 @@ - + @@ -120,7 +120,7 @@ - + @@ -223,7 +223,7 @@ - + @@ -238,15 +238,15 @@ - + - - + + - - + + @@ -262,8 +262,8 @@ - @@ -416,6 +416,29 @@ + + + + + + + + + + + + + @@ -455,7 +478,7 @@ - + @@ -510,7 +533,93 @@ This is only showcase app, not intended for production purposes. - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +