Merge branch 'develop' into uisearchbar-additions

This commit is contained in:
Stephen H. Gerstacker 2016-03-12 22:08:13 -05:00
commit 097467e07c
70 changed files with 747 additions and 306 deletions

View File

@ -455,3 +455,11 @@ extension NSTextField {
}
```
```swift
extension UITabBarItem {
public var rx_badgeValue: AnyObserver<String?> {}
}
```

View File

@ -46,7 +46,9 @@ let b /*: Observable<Int>*/ = Variable(2) // b = 2
// if a + b >= 0 {
// c = "\(a + b) is positive"
// }
let c = Observable.combineLatest(a, b) { $0 + $1 } // combines latest values of variables `a` and `b` using `+`
// combines latest values of variables `a` and `b` using `+`
let c = Observable.combineLatest(a.asObservable(), b.asObservable()) { $0 + $1 }
.filter { $0 >= 0 } // if `a + b >= 0` is true, `a + b` is passed to map operator
.map { "\($0) is positive" } // maps `a + b` to "\(a + b) is positive"

View File

@ -481,7 +481,7 @@ Disposed
Ended ----
```
**Every subscriber upon subscription usually generates it's own separate sequence of elements. Operators are stateless by default. There is vastly more stateless operators then stateful ones.**
**Every subscriber upon subscription usually generates it's own separate sequence of elements. Operators are stateless by default. There are vastly more stateless operators than stateful ones.**
## Sharing subscription and `shareReplay` operator
@ -771,7 +771,7 @@ Usually after you have fixed the error, you can remove the type annotations to c
## Debugging
Using debugger alone is useful, but you can also use `debug`. `debug` operator will print out all events to standard output and you can add also label those events.
Using debugger alone is useful, but usually using `debug` operator will be more efficient. `debug` operator will print out all events to standard output and you can add also label those events.
`debug` acts like a probe. Here is an example of using it:
@ -809,17 +809,34 @@ This is simply 4
Disposed
```
You can also use `subscribe` instead of `subscribeNext`
You can also easily create your version of the `debug` operator.
```swift
NSURLSession.sharedSession().rx_JSON(request)
.map { json in
return parse()
}
.subscribe { n in // this subscribes on all events including error and completed
print(n)
}
```
extension ObservableType {
public func myDebug(identifier: String) -> Observable<Self.E> {
return Observable.create { observer in
print("subscribed \(identifier)")
let subscription = self.subscribe { e in
print("event \(identifier) \(e)")
switch e {
case .Next(let value):
observer.on(.Next(value))
case .Error(let error):
observer.on(.Error(error))
case .Completed:
observer.on(.Completed)
}
}
return AnonymousDisposable {
print("disposing \(identifier)")
subscription.dispose()
}
}
}
}
```
## Debugging memory leaks
@ -964,7 +981,7 @@ self.rx_observe(CGRect.self, "view.frame", retainSelf: false)
### `rx_observeWeakly`
`rx_observeWeakly` has somewhat slower then `rx_observe` because it has to handle object deallocation in case of weak references.
`rx_observeWeakly` has somewhat slower than `rx_observe` because it has to handle object deallocation in case of weak references.
It can be used in all cases where `rx_observe` can be used and additionally

50
Documentation/Tips.md Normal file
View File

@ -0,0 +1,50 @@
Tips
====
* Always strive to model your systems or their parts as pure functions. Those pure functions can be tested easily and can be used to modify operator behaviors.
* When you are using Rx, first try to compose built-in operators.
* If using some combination of operators often, create your convenience operators.
e.g.
```swift
extension ObservableType where E: MaybeCool {
@warn_unused_result(message="http://git.io/rxs.uo")
public func coolElements()
-> Observable<E> {
return filter { e -> Bool in
return e.isCool
}
}
}
```
* Rx operators are as general as possible, but there will always be edge cases that will be hard to model. In those cases you can just create your own operator and possibly use one of the built-in operators as a reference.
* Always use operators to compose subscriptions.
**Avoid nesting subscribe calls at all cost. This is a bad smell.**
```swift
textField.rx_text.subscribeNext { text in
performURLRequest(text).subscribeNext { result in
...
}
.addDisposableTo(disposeBag)
}
.addDisposableTo(disposeBag)
```
**Preferred way of chaining disposables by using operators.**
```swift
textField.rx_text
.flatMapLatest { text in
// Assuming this doesn't fail and returns result on main scheduler,
// otherwise `catchError` and `observeOn(MainScheduler.instance)` can be used to
// correct this.
return performURLRequest(text)
}
...
.addDisposableTo(disposeBag) // only one top most disposable
```

View File

@ -0,0 +1,97 @@
Unit Tests
==========
## Testing custom operators
Library uses `RxTests` for all of RxSwift operator tests so you can take a look at AllTests-* target inside the project `Rx.xcworkspace`.
This is an example of a typical `RxSwift` operator unit test:
```swift
func testMap_Range() {
// Initializes test scheduler.
// Test scheduler implements virtual time that is
// detached from local machine clock.
// That enables running the simulation as fast as possible
// and proving that all events have been handled.
let scheduler = TestScheduler(initialClock: 0)
// Creates a mock hot observable sequence.
// The sequence will emit events at following
// times no matter is there some observer subscribed.
// (that's what hot means).
// This observable sequence will also record all subscriptions
// made during it's lifetime (`subscriptions` property).
let xs = scheduler.createHotObservable([
next(150, 1), // first argument is virtual time, second argument is element value
next(210, 0),
next(220, 1),
next(230, 2),
next(240, 4),
completed(300) // virtual time when completed is sent
])
// `start` method will by default:
// * run the simulation and record all events
// using observer referenced by `res`.
// * subscribe at virtual time 200
// * dispose subscription at virtual time 1000
let res = scheduler.start { xs.map { $0 * 2 } }
let correctMessages = [
next(210, 0 * 2),
next(220, 1 * 2),
next(230, 2 * 2),
next(240, 4 * 2),
completed(300)
]
let correctSubscriptions = [
Subscription(200, 300)
]
XCTAssertEqual(res.events, correctMessages)
XCTAssertEqual(xs.subscriptions, correctSubscriptions)
}
```
## Testing operator compositions (view models, components)
Examples how to test operator compositions are contained inside `Rx.xcworkspace` > `RxExample-iOSTests` target.
It easy to define `RxTests` extensions so you can write your tests in a readable way. Provided examples inside `RxExample-iOSTests` are just a tip how you can write those extensions, but there is a lot of possibilities how to write those tests.
```swift
// expected events and test data
let (
usernameEvents,
passwordEvents,
repeatedPasswordEvents,
loginTapEvents,
expectedValidatedUsernameEvents,
expectedSignupEnabledEvents
) = (
scheduler.parseEventsAndTimes("e---u1----u2-----u3-----------------", values: stringValues).first!,
scheduler.parseEventsAndTimes("e----------------------p1-----------", values: stringValues).first!,
scheduler.parseEventsAndTimes("e---------------------------p2---p1-", values: stringValues).first!,
scheduler.parseEventsAndTimes("------------------------------------", values: events).first!,
scheduler.parseEventsAndTimes("e---v--f--v--f---v--o----------------", values: validations).first!,
scheduler.parseEventsAndTimes("f--------------------------------t---", values: booleans).first!
)
```
## Integration tests
It is also possible to write integration tests by using `RxBlocking` operators.
Importing operators from `RxBlocking` library will enable blocking the current thread and wait for sequence results.
```swift
let result = try fetchResource(location)
.toBlocking()
.toArray()
XCTAssertEqual(result, expectedResult)
```

View File

@ -24,8 +24,11 @@ KVO observing, async operations and streams are all unified under [abstraction o
###### ... understand
* [why use rx?](Documentation/Why.md)
* how does RxSwift work? [Getting Started Guide](Documentation/GettingStarted.md)
* what is `Driver`, `ControlProperty`, and `Variable` ... and why do they exist? [Units](Documentation/Units.md)
* [the basics, getting started with RxSwift](Documentation/GettingStarted.md)
* [units](Documentation/Units.md) - what is `Driver`, `ControlProperty`, and `Variable` ... and why do they exist?
* [testing](Documentation/UnitTests.md)
* [tips and common errors](Documentation/Tips.md)
* [debugging](Documentation/GettingStarted.md#debugging)
* [the math behind Rx](Documentation/MathBehindRx.md)
* [what are hot and cold observable sequences?](Documentation/HotAndColdObservables.md)
* [what does the the public API look like?](Documentation/API.md)

View File

@ -1,3 +1,12 @@
/*:
> # IMPORTANT: To use `Rx.playground`, please:
1. Open `Rx.xcworkspace`
2. Build `RxSwift-OSX` scheme
3. And then open `Rx` playground in `Rx.xcworkspace` tree view.
4. Choose `View > Show Debug Area`
*/
//: [<< Previous](@previous) - [Index](Index)
import RxSwift

View File

@ -1,3 +1,12 @@
/*:
> # IMPORTANT: To use `Rx.playground`, please:
1. Open `Rx.xcworkspace`
2. Build `RxSwift-OSX` scheme
3. And then open `Rx` playground in `Rx.xcworkspace` tree view.
4. Choose `View > Show Debug Area`
*/
//: [<< Previous](@previous) - [Index](Index)
import Cocoa

View File

@ -1,3 +1,12 @@
/*:
> # IMPORTANT: To use `Rx.playground`, please:
1. Open `Rx.xcworkspace`
2. Build `RxSwift-OSX` scheme
3. And then open `Rx` playground in `Rx.xcworkspace` tree view.
4. Choose `View > Show Debug Area`
*/
//: [<< Previous](@previous) - [Index](Index)
import RxSwift

View File

@ -1,3 +1,12 @@
/*:
> # IMPORTANT: To use `Rx.playground`, please:
1. Open `Rx.xcworkspace`
2. Build `RxSwift-OSX` scheme
3. And then open `Rx` playground in `Rx.xcworkspace` tree view.
4. Choose `View > Show Debug Area`
*/
//: [<< Previous](@previous) - [Index](Index)
import RxSwift

View File

@ -1,3 +1,12 @@
/*:
> # IMPORTANT: To use `Rx.playground`, please:
1. Open `Rx.xcworkspace`
2. Build `RxSwift-OSX` scheme
3. And then open `Rx` playground in `Rx.xcworkspace` tree view.
4. Choose `View > Show Debug Area`
*/
//: [<< Previous](@previous) - [Index](Index)
import RxSwift

View File

@ -1,6 +1,6 @@
/*:
> # IMPORTANT: To use `RxSamples`, please:
> # IMPORTANT: To use `Rx.playground`, please:
1. Open `Rx.xcworkspace`
2. Build `RxSwift-OSX` scheme

View File

@ -1,3 +1,12 @@
/*:
> # IMPORTANT: To use `Rx.playground`, please:
1. Open `Rx.xcworkspace`
2. Build `RxSwift-OSX` scheme
3. And then open `Rx` playground in `Rx.xcworkspace` tree view.
4. Choose `View > Show Debug Area`
*/
//: [<< Index](@previous)
import RxSwift

View File

@ -1,3 +1,12 @@
/*:
> # IMPORTANT: To use `Rx.playground`, please:
1. Open `Rx.xcworkspace`
2. Build `RxSwift-OSX` scheme
3. And then open `Rx` playground in `Rx.xcworkspace` tree view.
4. Choose `View > Show Debug Area`
*/
//: [<< Previous](@previous) - [Index](Index)
import RxSwift

View File

@ -1,3 +1,12 @@
/*:
> # IMPORTANT: To use `Rx.playground`, please:
1. Open `Rx.xcworkspace`
2. Build `RxSwift-OSX` scheme
3. And then open `Rx` playground in `Rx.xcworkspace` tree view.
4. Choose `View > Show Debug Area`
*/
//: [<< Previous](@previous) - [Index](Index)
import RxSwift

View File

@ -1,3 +1,12 @@
/*:
> # IMPORTANT: To use `Rx.playground`, please:
1. Open `Rx.xcworkspace`
2. Build `RxSwift-OSX` scheme
3. And then open `Rx` playground in `Rx.xcworkspace` tree view.
4. Choose `View > Show Debug Area`
*/
//: [<< Previous](@previous) - [Index](Index)
import RxSwift

View File

@ -1,3 +1,12 @@
/*:
> # IMPORTANT: To use `Rx.playground`, please:
1. Open `Rx.xcworkspace`
2. Build `RxSwift-OSX` scheme
3. And then open `Rx` playground in `Rx.xcworkspace` tree view.
4. Choose `View > Show Debug Area`
*/
//: [<< Previous](@previous) - [Index](Index)
import RxSwift

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='6.0' target-platform='osx' display-mode='rendered'>
<playground version='6.0' target-platform='osx' display-mode='raw'>
<pages>
<page name='Index'/>
<page name='Introduction'/>

View File

@ -11,6 +11,11 @@
79E9DE8A1C3417FD009970AF /* DispatchQueueSchedulerQOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79E9DE881C3417FD009970AF /* DispatchQueueSchedulerQOS.swift */; };
79E9DE8B1C3417FD009970AF /* DispatchQueueSchedulerQOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79E9DE881C3417FD009970AF /* DispatchQueueSchedulerQOS.swift */; };
79E9DE8C1C3417FD009970AF /* DispatchQueueSchedulerQOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79E9DE881C3417FD009970AF /* DispatchQueueSchedulerQOS.swift */; };
7EDBAEB41C89B1A6006CBE67 /* UITabBarItem+RxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EDBAEAB1C89B1A5006CBE67 /* UITabBarItem+RxTests.swift */; };
7EDBAEBC1C89B9B7006CBE67 /* UITabBarItem+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EDBAEB71C89B9B7006CBE67 /* UITabBarItem+Rx.swift */; };
7EDBAEBE1C89B9B7006CBE67 /* UITabBarItem+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EDBAEB71C89B9B7006CBE67 /* UITabBarItem+Rx.swift */; };
7EDBAEBF1C89B9B7006CBE67 /* UITabBarItem+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EDBAEB71C89B9B7006CBE67 /* UITabBarItem+Rx.swift */; };
7EDBAEC31C89BCB9006CBE67 /* UITabBarItem+RxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EDBAEAB1C89B1A5006CBE67 /* UITabBarItem+RxTests.swift */; };
7F600F3F1C5D0C6C00535B1D /* UIRefreshControl+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F600F3D1C5D0C0100535B1D /* UIRefreshControl+Rx.swift */; };
7F600F401C5D0C6D00535B1D /* UIRefreshControl+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F600F3D1C5D0C0100535B1D /* UIRefreshControl+Rx.swift */; };
7F600F411C5D0C6E00535B1D /* UIRefreshControl+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F600F3D1C5D0C0100535B1D /* UIRefreshControl+Rx.swift */; };
@ -35,6 +40,8 @@
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 */; };
AAE623761C82475700FC7801 /* UIProgressView+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE623751C82475700FC7801 /* UIProgressView+Rx.swift */; };
AAE623771C82475700FC7801 /* UIProgressView+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE623751C82475700FC7801 /* UIProgressView+Rx.swift */; };
B1B7C3BD1BDD39DB0076934E /* TakeLast.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1B7C3BC1BDD39DB0076934E /* TakeLast.swift */; };
B1B7C3BE1BDD39DB0076934E /* TakeLast.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1B7C3BC1BDD39DB0076934E /* TakeLast.swift */; };
B1B7C3BF1BDD39DB0076934E /* TakeLast.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1B7C3BC1BDD39DB0076934E /* TakeLast.swift */; };
@ -635,6 +642,10 @@
C8B145011BD2D80100267DCE /* ImmediateScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8B144FF1BD2D80100267DCE /* ImmediateScheduler.swift */; };
C8B145021BD2D80100267DCE /* ImmediateScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8B144FF1BD2D80100267DCE /* ImmediateScheduler.swift */; };
C8B145031BD2D80100267DCE /* ImmediateScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8B144FF1BD2D80100267DCE /* ImmediateScheduler.swift */; };
C8B290891C94D64600E923D0 /* RxTest+Controls.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8B290841C94D55600E923D0 /* RxTest+Controls.swift */; };
C8B2908A1C94D64700E923D0 /* RxTest+Controls.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8B290841C94D55600E923D0 /* RxTest+Controls.swift */; };
C8B2908B1C94D64700E923D0 /* RxTest+Controls.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8B290841C94D55600E923D0 /* RxTest+Controls.swift */; };
C8B2908D1C94D6C500E923D0 /* UISearchBar+RxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8B2908C1C94D6C500E923D0 /* UISearchBar+RxTests.swift */; };
C8BCD3C71C1468D4005F1280 /* ShareReplay1WhileConnected.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8BCD3C61C1468D4005F1280 /* ShareReplay1WhileConnected.swift */; };
C8BCD3C81C1468D4005F1280 /* ShareReplay1WhileConnected.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8BCD3C61C1468D4005F1280 /* ShareReplay1WhileConnected.swift */; };
C8BCD3C91C1468D4005F1280 /* ShareReplay1WhileConnected.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8BCD3C61C1468D4005F1280 /* ShareReplay1WhileConnected.swift */; };
@ -1316,6 +1327,8 @@
/* Begin PBXFileReference section */
79E9DE881C3417FD009970AF /* DispatchQueueSchedulerQOS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DispatchQueueSchedulerQOS.swift; sourceTree = "<group>"; };
7EDBAEAB1C89B1A5006CBE67 /* UITabBarItem+RxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UITabBarItem+RxTests.swift"; sourceTree = "<group>"; };
7EDBAEB71C89B9B7006CBE67 /* UITabBarItem+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UITabBarItem+Rx.swift"; sourceTree = "<group>"; };
7F600F3D1C5D0C0100535B1D /* UIRefreshControl+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIRefreshControl+Rx.swift"; sourceTree = "<group>"; };
7F600F421C5D0D2D00535B1D /* UIRefreshControl+RxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIRefreshControl+RxTests.swift"; sourceTree = "<group>"; };
842A5A281C357F7D003568D5 /* NSTextStorage+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSTextStorage+Rx.swift"; sourceTree = "<group>"; };
@ -1325,6 +1338,7 @@
84C225A21C33F00B008724EC /* RxTextStorageDelegateProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxTextStorageDelegateProxy.swift; sourceTree = "<group>"; };
9BA1CBD11C0F7C0A0044B50A /* UIActivityIndicatorView+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIActivityIndicatorView+Rx.swift"; sourceTree = "<group>"; };
A111CE961B91C97C00D0DCEE /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
AAE623751C82475700FC7801 /* UIProgressView+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIProgressView+Rx.swift"; sourceTree = "<group>"; };
B1B7C3BC1BDD39DB0076934E /* TakeLast.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TakeLast.swift; sourceTree = "<group>"; };
B1D8998E1BF653410027B05C /* Timeout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Timeout.swift; sourceTree = "<group>"; };
C807F3611C2ACED300017910 /* TestSchedulerVirtualTimeConverter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestSchedulerVirtualTimeConverter.swift; sourceTree = "<group>"; };
@ -1603,6 +1617,8 @@
C8A56AD71AD7424700B4673B /* RxSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RxSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
C8B144FA1BD2D44500267DCE /* ConcurrentMainScheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConcurrentMainScheduler.swift; sourceTree = "<group>"; };
C8B144FF1BD2D80100267DCE /* ImmediateScheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImmediateScheduler.swift; sourceTree = "<group>"; };
C8B290841C94D55600E923D0 /* RxTest+Controls.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "RxTest+Controls.swift"; sourceTree = "<group>"; };
C8B2908C1C94D6C500E923D0 /* UISearchBar+RxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UISearchBar+RxTests.swift"; sourceTree = "<group>"; };
C8BCD3C61C1468D4005F1280 /* ShareReplay1WhileConnected.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShareReplay1WhileConnected.swift; sourceTree = "<group>"; };
C8BCD3EC1C14B5FB005F1280 /* UIView+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+Rx.swift"; sourceTree = "<group>"; };
C8BCD3F11C14B62B005F1280 /* NSView+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSView+Rx.swift"; sourceTree = "<group>"; };
@ -2175,6 +2191,7 @@
C8D132511C42DA7F00B59FFF /* TestImplementations */,
C83508D91C38706D0027C24C /* CLLocationManager+RxTests.swift */,
8476A01F1C3D5D580040BA22 /* UIImagePickerController+RxTests.swift */,
C8B290841C94D55600E923D0 /* RxTest+Controls.swift */,
C83508DA1C38706D0027C24C /* Control+RxTests+Cocoa.swift */,
C83508DB1C38706D0027C24C /* Control+RxTests+UIKit.swift */,
C83508DC1C38706D0027C24C /* Control+RxTests.swift */,
@ -2200,6 +2217,8 @@
C83508F01C38706D0027C24C /* SentMessageTest.swift */,
C83508F11C38706D0027C24C /* UIView+RxTests.swift */,
7F600F421C5D0D2D00535B1D /* UIRefreshControl+RxTests.swift */,
7EDBAEAB1C89B1A5006CBE67 /* UITabBarItem+RxTests.swift */,
C8B2908C1C94D6C500E923D0 /* UISearchBar+RxTests.swift */,
);
path = RxCocoaTests;
sourceTree = "<group>";
@ -2322,6 +2341,7 @@
C882540A1B8A752B00B02D69 /* UIGestureRecognizer+Rx.swift */,
C882540B1B8A752B00B02D69 /* UIImageView+Rx.swift */,
C882540C1B8A752B00B02D69 /* UILabel+Rx.swift */,
AAE623751C82475700FC7801 /* UIProgressView+Rx.swift */,
7F600F3D1C5D0C0100535B1D /* UIRefreshControl+Rx.swift */,
C882540D1B8A752B00B02D69 /* UIScrollView+Rx.swift */,
C882540E1B8A752B00B02D69 /* UISearchBar+Rx.swift */,
@ -2336,6 +2356,7 @@
9BA1CBD11C0F7C0A0044B50A /* UIActivityIndicatorView+Rx.swift */,
8479BC4A1C3ACED100FB8B54 /* UIImagePickerController+Rx.swift */,
C8BCD3EC1C14B5FB005F1280 /* UIView+Rx.swift */,
7EDBAEB71C89B9B7006CBE67 /* UITabBarItem+Rx.swift */,
);
path = iOS;
sourceTree = "<group>";
@ -3244,6 +3265,7 @@
C882542E1B8A752B00B02D69 /* UILabel+Rx.swift in Sources */,
C88254211B8A752B00B02D69 /* RxSearchBarDelegateProxy.swift in Sources */,
C80DDEA71BCE69BA006A1832 /* ObservableConvertibleType+Driver.swift in Sources */,
7EDBAEBC1C89B9B7006CBE67 /* UITabBarItem+Rx.swift in Sources */,
C839365F1C70E02200A9A09E /* UIApplication+Rx.swift in Sources */,
C80DDE9F1BCE69BA006A1832 /* Driver+Subscription.swift in Sources */,
C811C89D1C24D80100A2DDD4 /* DeallocObservable.swift in Sources */,
@ -3251,6 +3273,7 @@
C80D338F1B91EF9E0014629D /* Observable+Bind.swift in Sources */,
C88254311B8A752B00B02D69 /* UISegmentedControl+Rx.swift in Sources */,
C8093EED1B8A732E0088E94D /* KVOObservable.swift in Sources */,
AAE623761C82475700FC7801 /* UIProgressView+Rx.swift in Sources */,
C8DB968D1BF7595D0084BD53 /* KVORepresentable+Swift.swift in Sources */,
C80DDEB11BCE8CA3006A1832 /* Driver+Operators+arity.swift in Sources */,
C88254281B8A752B00B02D69 /* UIButton+Rx.swift in Sources */,
@ -3372,6 +3395,7 @@
C835094B1C38706E0027C24C /* AnonymousObservable+Test.swift in Sources */,
C835092E1C38706E0027C24C /* ControlEventTests.swift in Sources */,
C83509531C38706E0027C24C /* Observable+AggregateTest.swift in Sources */,
C8B290891C94D64600E923D0 /* RxTest+Controls.swift in Sources */,
C83509291C38706E0027C24C /* PerformanceTools.swift in Sources */,
C835096A1C38706E0027C24C /* TestErrors.swift in Sources */,
C83509561C38706E0027C24C /* Observable+ConcurrencyTest.swift in Sources */,
@ -3385,6 +3409,7 @@
C835095F1C38706E0027C24C /* Observable+SubscriptionTest.swift in Sources */,
C83509451C38706E0027C24C /* Observable.Extensions.swift in Sources */,
C835093B1C38706E0027C24C /* RXObjCRuntime+Testing.m in Sources */,
C8B2908D1C94D6C500E923D0 /* UISearchBar+RxTests.swift in Sources */,
C83509641C38706E0027C24C /* VariableTest.swift in Sources */,
C83509461C38706E0027C24C /* PrimitiveHotObservable.swift in Sources */,
C835097E1C38726E0027C24C /* RxMutableBox.swift in Sources */,
@ -3396,6 +3421,7 @@
C83509331C38706E0027C24C /* Driver+Extensions.swift in Sources */,
C835094F1C38706E0027C24C /* CurrentThreadSchedulerTest.swift in Sources */,
C835093E1C38706E0027C24C /* UIView+RxTests.swift in Sources */,
7EDBAEB41C89B1A6006CBE67 /* UITabBarItem+RxTests.swift in Sources */,
C83509411C38706E0027C24C /* BackgroundThreadPrimitiveHotObservable.swift in Sources */,
C83509581C38706E0027C24C /* Observable+MultipleTest+CombineLatest.swift in Sources */,
C83509651C38706E0027C24C /* VirtualSchedulerTest.swift in Sources */,
@ -3444,6 +3470,7 @@
C83509EE1C3875580027C24C /* Observable.Extensions.swift in Sources */,
C83509BD1C38750D0027C24C /* ControlPropertyTests.swift in Sources */,
C83509E11C3875500027C24C /* TestVirtualScheduler.swift in Sources */,
C8B2908A1C94D64700E923D0 /* RxTest+Controls.swift in Sources */,
C8350A181C38756A0027C24C /* VariableTest.swift in Sources */,
C83509EF1C3875580027C24C /* PrimitiveHotObservable.swift in Sources */,
C83509FB1C38755D0027C24C /* Observable+BindingTest.swift in Sources */,
@ -3481,6 +3508,7 @@
C8350A121C38756A0027C24C /* Observable+StandardSequenceOperatorsTest.swift in Sources */,
C83509C31C3875220027C24C /* KVOObservableTests.swift in Sources */,
C83509F91C38755D0027C24C /* MainSchedulerTests.swift in Sources */,
7EDBAEC31C89BCB9006CBE67 /* UITabBarItem+RxTests.swift in Sources */,
C83509AB1C3874D20027C24C /* XCTest+AllTests.swift in Sources */,
C83509C11C3875220027C24C /* Driver+Extensions.swift in Sources */,
C83509DD1C38754C0027C24C /* EquatableArray.swift in Sources */,
@ -3534,6 +3562,7 @@
C8350A081C38755E0027C24C /* Observable+AggregateTest.swift in Sources */,
C83509E81C3875580027C24C /* PrimitiveMockObserver.swift in Sources */,
C83509BE1C3875100027C24C /* DelegateProxyTest+Cocoa.swift in Sources */,
C8B2908B1C94D64700E923D0 /* RxTest+Controls.swift in Sources */,
C8350A1B1C38756B0027C24C /* Observable+SingleTest.swift in Sources */,
C8350A231C38756B0027C24C /* VirtualSchedulerTest.swift in Sources */,
C83509E51C3875580027C24C /* MySubject.swift in Sources */,
@ -4173,6 +4202,7 @@
C8F0C03A1BBBFBB9001B112F /* ControlTarget.swift in Sources */,
C8F0C03B1BBBFBB9001B112F /* UISearchBar+Rx.swift in Sources */,
C8F0C03C1BBBFBB9001B112F /* ItemEvents.swift in Sources */,
7EDBAEBF1C89B9B7006CBE67 /* UITabBarItem+Rx.swift in Sources */,
C8DB968B1BF756F40084BD53 /* KVORepresentable+CoreGraphics.swift in Sources */,
C8FD21B11C67E14C00863EC3 /* UIBindingObserver.swift in Sources */,
C8F0C03D1BBBFBB9001B112F /* RxTableViewDataSourceType.swift in Sources */,
@ -4248,6 +4278,7 @@
D203C50D1BB9C53E00D02D00 /* UISegmentedControl+Rx.swift in Sources */,
C8C4B4C41C17727000828BD5 /* MessageSentObserver.swift in Sources */,
D2138C861BB9BEBE00339B5C /* Observable+Bind.swift in Sources */,
AAE623771C82475700FC7801 /* UIProgressView+Rx.swift in Sources */,
D203C50A1BB9C53E00D02D00 /* UILabel+Rx.swift in Sources */,
D203C4F51BB9C52900D02D00 /* ItemEvents.swift in Sources */,
C8BCD3F61C14B6D1005F1280 /* NSLayoutConstraint+Rx.swift in Sources */,
@ -4265,6 +4296,7 @@
9D71C4D21BF08191006E8F59 /* UIButton+Rx.swift in Sources */,
D203C4FD1BB9C53700D02D00 /* RxSearchBarDelegateProxy.swift in Sources */,
D2138C8A1BB9BEBE00339B5C /* Logging.swift in Sources */,
7EDBAEBE1C89B9B7006CBE67 /* UITabBarItem+Rx.swift in Sources */,
C8DB968A1BF756F40084BD53 /* KVORepresentable+CoreGraphics.swift in Sources */,
C8FD21B01C67E14C00863EC3 /* UIBindingObserver.swift in Sources */,
D203C50F1BB9C53E00D02D00 /* UIStepper+Rx.swift in Sources */,

View File

@ -20,7 +20,7 @@ extension NSNotificationCenter {
- returns: Observable sequence of posted notifications.
*/
@warn_unused_result(message="http://git.io/rxs.uo")
public func rx_notification(name: String, object: AnyObject? = nil) -> Observable<NSNotification> {
public func rx_notification(name: String?, object: AnyObject? = nil) -> Observable<NSNotification> {
return Observable.create { [weak object] observer in
let nsObserver = self.addObserverForName(name, object: object, queue: nil) { notification in
observer.on(.Next(notification))

View File

@ -180,7 +180,7 @@ extension NSURLSession {
public func rx_data(request: NSURLRequest) -> Observable<NSData> {
return rx_response(request).map { (data, response) -> NSData in
if 200 ..< 300 ~= response.statusCode {
return data ?? NSData()
return data
}
else {
throw RxCocoaURLError.HTTPRequestFailed(response: response, data: data)
@ -209,7 +209,7 @@ extension NSURLSession {
public func rx_JSON(request: NSURLRequest) -> Observable<AnyObject> {
return rx_data(request).map { (data) -> AnyObject in
do {
return try NSJSONSerialization.JSONObjectWithData(data ?? NSData(), options: [])
return try NSJSONSerialization.JSONObjectWithData(data, options: [])
} catch let error {
throw RxCocoaURLError.DeserializationError(error: error)
}

View File

@ -41,6 +41,8 @@ static NSMutableDictionary *forwardableSelectorsPerClass = nil;
for (unsigned int i = 0; i < numberOfBaseProtocols; ++i) {
[selectors unionSet:[self collectSelectorsForProtocol:pSubprotocols[i]]];
}
free(pSubprotocols);
return selectors;
}

View File

@ -112,9 +112,7 @@ extension UICollectionView {
For more information take a look at `DelegateProxyType` protocol documentation.
*/
public var rx_dataSource: DelegateProxy {
get {
return proxyForObject(RxCollectionViewDataSourceProxy.self, self)
}
return proxyForObject(RxCollectionViewDataSourceProxy.self, self)
}
/**

View File

@ -0,0 +1,30 @@
//
// UIProgressView+Rx.swift
// Rx
//
// Created by Samuel Bae on 2/27/16.
// Copyright © 2016 Krunoslav Zaher. All rights reserved.
//
#if os(iOS) || os(tvOS)
import Foundation
#if !RX_NO_MODULE
import RxSwift
#endif
import UIKit
extension UIProgressView {
/**
Bindable sink for `progress` property
*/
public var rx_progress: AnyObserver<Float> {
return UIBindingObserver(UIElement: self) { progressView, progress in
progressView.progress = progress
}.asObserver()
}
}
#endif

View File

@ -0,0 +1,30 @@
//
// UITabBarItem+Rx.swift
// Rx
//
// Created by Mateusz Derks on 04/03/16.
// Copyright © 2016 Krunoslav Zaher. All rights reserved.
//
#if os(iOS) || os(tvOS)
import Foundation
import UIKit
#if !RX_NO_MODULE
import RxSwift
#endif
extension UITabBarItem {
/**
Bindable sink for `badgeValue` property.
*/
public var rx_badgeValue: AnyObserver<String?> {
return UIBindingObserver(UIElement: self) { tabBarItem, badgeValue in
tabBarItem.badgeValue = badgeValue
}.asObserver()
}
}
#endif

View File

@ -35,7 +35,14 @@ extension UITextView {
let text = self?.text ?? ""
let textChanged = self?.textStorage
// This project uses text storage notifications because
// that's the only way to catch autocorrect changes
// in all cases. Other suggestions are welcome.
.rx_didProcessEditingRangeChangeInLength
// This observe on is here because text storage
// will emit event while process is not completely done,
// so rebinding a value will cause an exception to be thrown.
.observeOn(MainScheduler.asyncInstance)
.map { _ in
return self?.textStorage.string ?? ""
}

View File

@ -18,9 +18,7 @@ struct ItemPath : CustomDebugStringConvertible {
let itemIndex: Int
var debugDescription : String {
get {
return "(\(sectionIndex), \(itemIndex))"
}
return "(\(sectionIndex), \(itemIndex))"
}
}
@ -51,20 +49,18 @@ public struct Changeset<S: SectionModelType> : CustomDebugStringConvertible {
}
public var debugDescription : String {
get {
let serializedSections = "[\n" + finalSections.map { "\($0)" }.joinWithSeparator(",\n") + "\n]\n"
return " >> Final sections"
let serializedSections = "[\n" + finalSections.map { "\($0)" }.joinWithSeparator(",\n") + "\n]\n"
return " >> Final sections"
+ " \n\(serializedSections)"
+ (insertedSections.count > 0 || deletedSections.count > 0 || movedSections.count > 0 || updatedSections.count > 0 ? "\nSections:" : "")
+ (insertedSections.count > 0 ? "\ninsertedSections:\n\t\(insertedSections)" : "")
+ (deletedSections.count > 0 ? "\ndeletedSections:\n\t\(deletedSections)" : "")
+ (movedSections.count > 0 ? "\nmovedSections:\n\t\(movedSections)" : "")
+ (updatedSections.count > 0 ? "\nupdatesSections:\n\t\(updatedSections)" : "")
+ (insertedItems.count > 0 || deletedItems.count > 0 || movedItems.count > 0 || updatedItems.count > 0 ? "\nItems:" : "")
+ (insertedItems.count > 0 || deletedItems.count > 0 || movedItems.count > 0 || updatedItems.count > 0 ? "\nItems:" : "")
+ (insertedItems.count > 0 ? "\ninsertedItems:\n\t\(insertedItems)" : "")
+ (deletedItems.count > 0 ? "\ndeletedItems:\n\t\(deletedItems)" : "")
+ (movedItems.count > 0 ? "\nmovedItems:\n\t\(movedItems)" : "")
+ (updatedItems.count > 0 ? "\nupdatedItems:\n\t\(updatedItems)" : "")
}
}
}

View File

@ -33,19 +33,17 @@ enum EditEvent : CustomDebugStringConvertible {
extension EditEvent {
var debugDescription: String {
get {
switch self {
case .Inserted:
return "Inserted"
case .Deleted:
return "Deleted"
case .Moved:
return "Moved"
case .MovedAutomatically:
return "MovedAutomatically"
case .Untouched:
return "Untouched"
}
switch self {
case .Inserted:
return "Inserted"
case .Deleted:
return "Deleted"
case .Moved:
return "Moved"
case .MovedAutomatically:
return "MovedAutomatically"
case .Untouched:
return "Untouched"
}
}
}
@ -57,9 +55,7 @@ struct SectionAdditionalInfo : CustomDebugStringConvertible {
extension SectionAdditionalInfo {
var debugDescription: String {
get {
return "\(event), \(indexAfterDelete)"
}
return "\(event), \(indexAfterDelete)"
}
}
@ -70,9 +66,7 @@ struct ItemAdditionalInfo : CustomDebugStringConvertible {
extension ItemAdditionalInfo {
var debugDescription: String {
get {
return "\(event) \(indexAfterDelete)"
}
return "\(event) \(indexAfterDelete)"
}
}

View File

@ -25,9 +25,7 @@ public struct SectionModel<Section, ItemType> : SectionModelType, CustomStringCo
}
public var description: String {
get {
return "\(self.model) > \(items)"
}
return "\(self.model) > \(items)"
}
}
@ -48,15 +46,11 @@ public struct HashableSectionModel<Section: Hashable, ItemType: Hashable> : Hash
}
public var description: String {
get {
return "HashableSectionModel(model: \"\(self.model)\", items: \(items))"
}
return "HashableSectionModel(model: \"\(self.model)\", items: \(items))"
}
public var hashValue: Int {
get {
return self.model.hashValue
}
return self.model.hashValue
}
}

View File

@ -70,7 +70,11 @@ class APIWrappersViewController: ViewController {
// MARK: UISegmentedControl
segmentedControl.rx_value
// also test two way binding
let segmentedValue = Variable(0)
segmentedControl.rx_value <-> segmentedValue
segmentedValue.asObservable()
.subscribeNext { [weak self] x in
self?.debug("UISegmentedControl value \(x)")
}
@ -79,7 +83,11 @@ class APIWrappersViewController: ViewController {
// MARK: UISwitch
switcher.rx_value
// also test two way binding
let switchValue = Variable(false)
switcher.rx_value <-> switchValue
switchValue.asObservable()
.subscribeNext { [weak self] x in
self?.debug("UISwitch value \(x)")
}
@ -103,7 +111,11 @@ class APIWrappersViewController: ViewController {
// MARK: UISlider
slider.rx_value
// also test two way binding
let sliderValue = Variable<Float>(0.0)
slider.rx_value <-> sliderValue
sliderValue.asObservable()
.subscribeNext { [weak self] x in
self?.debug("UISlider value \(x)")
}
@ -112,7 +124,12 @@ class APIWrappersViewController: ViewController {
// MARK: UIDatePicker
datePicker.rx_date
// also test two way binding
let dateValue = Variable(NSDate())
datePicker.rx_date <-> dateValue
dateValue.asObservable()
.subscribeNext { [weak self] x in
self?.debug("UIDatePicker date \(x)")
}
@ -121,7 +138,11 @@ class APIWrappersViewController: ViewController {
// MARK: UITextField
textField.rx_text
// also test two way binding
let textValue = Variable("")
textField.rx_text <-> textValue
textValue.asObservable()
.subscribeNext { [weak self] x in
self?.debug("UITextField text \(x)")
}
@ -139,7 +160,11 @@ class APIWrappersViewController: ViewController {
// MARK: UITextView
textView.rx_text
// also test two way binding
let textViewValue = Variable("")
textView.rx_text <-> textViewValue
textViewValue.asObservable()
.subscribeNext { [weak self] x in
self?.debug("UITextView event \(x)")
}

View File

@ -23,14 +23,14 @@ private extension UILabel {
private extension UIView {
var rx_driveAuthorization: AnyObserver<Bool> {
return UIBindingObserver(UIElement: self) { label, authorized in
return UIBindingObserver(UIElement: self) { view, authorized in
if authorized {
label.hidden = true
label.superview?.sendSubviewToBack(label)
view.hidden = true
view.superview?.sendSubviewToBack(view)
}
else {
label.hidden = false
label.superview?.bringSubviewToFront(label)
view.hidden = false
view.superview?.bringSubviewToFront(view)
}
}.asObserver()
}
@ -48,7 +48,6 @@ class GeolocationViewController: ViewController {
let geolocationService = GeolocationService.instance
geolocationService.autorized
.drive(noGeolocationView.rx_driveAuthorization)
.addDisposableTo(disposeBag)

View File

@ -68,7 +68,7 @@ class ImagePickerController: ViewController {
.take(1)
}
.map { info in
return info[UIImagePickerControllerOriginalImage] as? UIImage
return info[UIImagePickerControllerEditedImage] as? UIImage
}
.bindTo(imageView.rx_image)
.addDisposableTo(disposeBag)

View File

@ -23,9 +23,7 @@ struct User: Equatable, CustomDebugStringConvertible {
extension User {
var debugDescription: String {
get {
return firstName + " " + lastName
}
return firstName + " " + lastName
}
}

View File

@ -20,9 +20,7 @@ class ReachabilityService {
private let _reachabilityChangedSubject = PublishSubject<ReachabilityStatus>()
private var reachabilityChanged: Observable<ReachabilityStatus> {
get {
return _reachabilityChangedSubject.asObservable()
}
return _reachabilityChangedSubject.asObservable()
}
// singleton

View File

@ -35,13 +35,11 @@ public struct BagKey : Hashable {
let key: Int
public var hashValue: Int {
get {
if let uniqueIdentity = uniqueIdentity {
return hash(key) ^ (unsafeAddressOf(uniqueIdentity).hashValue)
}
else {
return hash(key)
}
if let uniqueIdentity = uniqueIdentity {
return hash(key) ^ (unsafeAddressOf(uniqueIdentity).hashValue)
}
else {
return hash(key)
}
}
}
@ -212,9 +210,7 @@ extension Bag {
A textual representation of `self`, suitable for debugging.
*/
public var debugDescription : String {
get {
return "\(self.count) elements in Bag"
}
return "\(self.count) elements in Bag"
}
}

View File

@ -49,28 +49,22 @@ public struct Queue<T>: SequenceType {
}
private var dequeueIndex: Int {
get {
let index = _pushNextIndex - count
return index < 0 ? index + _storage.count : index
}
let index = _pushNextIndex - count
return index < 0 ? index + _storage.count : index
}
/**
- returns: Is queue empty.
*/
public var isEmpty: Bool {
get {
return count == 0
}
return count == 0
}
/**
- returns: Number of elements inside queue.
*/
public var count: Int {
get {
return _count
}
return _count
}
/**

View File

@ -23,9 +23,7 @@ public final class AnonymousDisposable : DisposeBase, Cancelable {
- returns: Was resource disposed.
*/
public var disposed: Bool {
get {
return _disposed == 1
}
return _disposed == 1
}
/**

View File

@ -23,9 +23,7 @@ public final class BinaryDisposable : DisposeBase, Cancelable {
- returns: Was resource disposed.
*/
public var disposed: Bool {
get {
return _disposed > 0
}
return _disposed > 0
}
/**

View File

@ -33,9 +33,7 @@ public class BooleanDisposable : Disposable, Cancelable {
- returns: Was resource disposed.
*/
public var disposed: Bool {
get {
return _disposed
}
return _disposed
}
/**

View File

@ -20,10 +20,8 @@ public class CompositeDisposable : DisposeBase, Disposable, Cancelable {
private var _disposables: Bag<Disposable>? = Bag()
public var disposed: Bool {
get {
_lock.lock(); defer { _lock.unlock() }
return _disposables == nil
}
_lock.lock(); defer { _lock.unlock() }
return _disposables == nil
}
public override init() {
@ -82,10 +80,8 @@ public class CompositeDisposable : DisposeBase, Disposable, Cancelable {
- returns: Gets the number of disposables contained in the `CompositeDisposable`.
*/
public var count: Int {
get {
_lock.lock(); defer { _lock.unlock() }
return _disposables?.count ?? 0
}
_lock.lock(); defer { _lock.unlock() }
return _disposables?.count ?? 0
}
/**

View File

@ -21,10 +21,8 @@ public class RefCountDisposable : DisposeBase, Cancelable {
- returns: Was resource disposed.
*/
public var disposed: Bool {
get {
_lock.lock(); defer { _lock.unlock() }
return _disposable == nil
}
_lock.lock(); defer { _lock.unlock() }
return _disposable == nil
}
/**

View File

@ -28,9 +28,7 @@ public class ScheduledDisposable : Cancelable {
- returns: Was resource disposed.
*/
public var disposed: Bool {
get {
return _disposed == 1
}
return _disposed == 1
}
/**

View File

@ -22,9 +22,7 @@ public class SerialDisposable : DisposeBase, Cancelable {
- returns: Was resource disposed.
*/
public var disposed: Bool {
get {
return _disposed
}
return _disposed
}
/**

View File

@ -25,9 +25,7 @@ public class SingleAssignmentDisposable : DisposeBase, Disposable, Cancelable {
- returns: A value that indicates whether the object is disposed.
*/
public var disposed: Bool {
get {
return _disposed
}
return _disposed
}
/**

View File

@ -34,11 +34,11 @@ public enum RxError
*/
case ArgumentOutOfRange
/**
Sequence doesn't contain any element.
Sequence doesn't contain any elements.
*/
case NoElements
/**
Sequence contains more then one element.
Sequence contains more than one element.
*/
case MoreThanOneElement
/**
@ -62,11 +62,11 @@ public extension RxError {
case .ArgumentOutOfRange:
return "Argument out of range."
case .NoElements:
return "Sequence doesn't contain any element."
return "Sequence doesn't contain any elements."
case .MoreThanOneElement:
return "Sequence contains more then one element."
return "Sequence contains more than one element."
case .Timeout:
return "Sequence timeout"
return "Sequence timeout."
}
}
}

View File

@ -37,15 +37,13 @@ extension Event {
- returns: Description of event
*/
public var debugDescription: String {
get {
switch self {
case .Next(let value):
return "Next(\(value))"
case .Error(let error):
return "Error(\(error))"
case .Completed:
return "Completed"
}
switch self {
case .Next(let value):
return "Next(\(value))"
case .Error(let error):
return "Error(\(error))"
case .Completed:
return "Completed"
}
}
}
@ -55,35 +53,29 @@ extension Event {
- returns: Is `Completed` or `Error` event
*/
public var isStopEvent: Bool {
get {
switch self {
case .Next: return false
case .Error, .Completed: return true
}
switch self {
case .Next: return false
case .Error, .Completed: return true
}
}
/**
- returns: If `Next` event, returns element value.
*/
public var element: Element? {
get {
if case .Next(let value) = self {
return value
}
return nil
if case .Next(let value) = self {
return value
}
return nil
}
/**
- returns: If `Error` event, returns error.
*/
public var error: ErrorType? {
get {
if case .Error(let error) = self {
return error
}
return nil
if case .Error(let error) = self {
return error
}
return nil
}
}

View File

@ -31,7 +31,7 @@ extension ObservableType {
- parameter onError: Action to invoke upon errored termination of the observable sequence.
- parameter onCompleted: Action to invoke upon graceful termination of the observable sequence.
- parameter onDisposed: Action to invoke upon any type of termination of sequence (if the sequence has
gracefully completed, errored, or if the generation is cancelled by disposing subscription)
gracefully completed, errored, or if the generation is cancelled by disposing subscription).
- returns: Subscription object used to unsubscribe from the observable sequence.
*/
@warn_unused_result(message="http://git.io/rxs.ud")
@ -119,7 +119,7 @@ extension ObservableType {
public extension ObservableType {
/**
All internal subscribe calls go through this method
All internal subscribe calls go through this method.
*/
@warn_unused_result(message="http://git.io/rxs.ud")
func subscribeSafe<O: ObserverType where O.E == E>(observer: O) -> Disposable {

View File

@ -25,7 +25,7 @@ public protocol ObservableType : ObservableConvertibleType {
**Next\* (Error | Completed)?**
* sequences can produce zero or more elements so zero or more `Next` events can be sent to `observer`
* once an `Error` or `Completed` event is sent, the sequence terminates and can't produce any other element
* once an `Error` or `Completed` event is sent, the sequence terminates and can't produce any other elements
It is possible that events are sent from different threads, but no two events can be sent concurrently to
`observer`.

View File

@ -36,8 +36,8 @@ class SingleAsyncSink<ElementType, O: ObserverType where O.E == ElementType> : S
}
if _seenValue == false {
forwardOn(.Next(value))
_seenValue = true
forwardOn(.Next(value))
} else {
forwardOn(.Error(RxError.MoreThanOneElement))
dispose()

View File

@ -76,9 +76,7 @@ class WithLatestFromSecond<FirstType, SecondType, ResultType, O: ObserverType wh
private let _disposable: Disposable
var _lock: NSRecursiveLock {
get {
return _parent._lock
}
return _parent._lock
}
init(parent: Parent, disposable: Disposable) {

View File

@ -32,8 +32,6 @@ extension RxMutableBox {
- returns: Box description.
*/
var debugDescription: String {
get {
return "MutatingBox(\(self.value))"
}
return "MutatingBox(\(self.value))"
}
}

View File

@ -20,9 +20,7 @@ public class ConcurrentDispatchQueueScheduler: SchedulerType {
private let _queue : dispatch_queue_t
public var now : NSDate {
get {
return NSDate()
}
return NSDate()
}
// leeway for scheduling timers

View File

@ -25,9 +25,7 @@ public final class ConcurrentMainScheduler : SchedulerType {
- returns: Current time.
*/
public var now : NSDate {
get {
return _mainScheduler.now
}
return _mainScheduler.now
}
private init(mainScheduler: MainScheduler) {

View File

@ -19,9 +19,7 @@ struct ScheduledItem<T>
private let _disposable = SingleAssignmentDisposable()
var disposed: Bool {
get {
return _disposable.disposed
}
return _disposable.disposed
}
init(action: Action, state: T) {

View File

@ -34,6 +34,12 @@ public final class MainScheduler : SerialDispatchQueueScheduler {
*/
public static let instance = MainScheduler()
/**
Singleton instance of `MainScheduler` that always schedules work asynchronously
and doesn't perform optimizations for calls scheduled from main thread.
*/
public static let asyncInstance = SerialDispatchQueueScheduler(serialQueue: dispatch_get_main_queue())
/**
In case this method is called on a background thread it will throw an exception.
*/

View File

@ -35,9 +35,7 @@ public class SerialDispatchQueueScheduler: SchedulerType {
- returns: Current time.
*/
public var now : NSDate {
get {
return NSDate()
}
return NSDate()
}
// leeway for scheduling timers

View File

@ -251,9 +251,7 @@ extension VirtualTimeScheduler {
A textual representation of `self`, suitable for debugging.
*/
public var debugDescription: String {
get {
return self._schedulerQueue.debugDescription
}
return self._schedulerQueue.debugDescription
}
}
@ -266,9 +264,7 @@ class VirtualSchedulerItem<Time>
let id: Int
var disposed: Bool {
get {
return disposable.disposed
}
return disposable.disposed
}
var disposable = SingleAssignmentDisposable()

View File

@ -35,9 +35,7 @@ final public class PublishSubject<Element>
Indicates whether the subject has been disposed.
*/
public var disposed: Bool {
get {
return _disposed
}
return _disposed
}
/**

View File

@ -37,9 +37,7 @@ extension Recorded {
A textual representation of `self`, suitable for debugging.
*/
public var debugDescription: String {
get {
return "\(value) @ \(time)"
}
return "\(value) @ \(time)"
}
}

View File

@ -50,9 +50,7 @@ public struct Subscription
The hash value.
*/
public var hashValue : Int {
get {
return subscribe.hashValue ^ unsubscribe.hashValue
}
return subscribe.hashValue ^ unsubscribe.hashValue
}
}
@ -61,10 +59,8 @@ extension Subscription {
A textual representation of `self`, suitable for debugging.
*/
public var debugDescription : String {
get {
let infiniteText = "Infinity"
return "(\(subscribe) : \(unsubscribe != Int.max ? String(unsubscribe) : infiniteText))"
}
let infiniteText = "Infinity"
return "(\(subscribe) : \(unsubscribe != Int.max ? String(unsubscribe) : infiniteText))"
}
}

View File

@ -468,11 +468,13 @@ _ObservableStandardSequenceOperatorsTest.allTests = [
("testSingle_One", { _ObservableStandardSequenceOperatorsTest.setUp(); _ObservableStandardSequenceOperatorsTest.testSingle_One(); _ObservableStandardSequenceOperatorsTest.tearDown(); }),
("testSingle_Many", { _ObservableStandardSequenceOperatorsTest.setUp(); _ObservableStandardSequenceOperatorsTest.testSingle_Many(); _ObservableStandardSequenceOperatorsTest.tearDown(); }),
//("testSingle_Error", { _ObservableStandardSequenceOperatorsTest.setUp(); _ObservableStandardSequenceOperatorsTest.testSingle_Error(); _ObservableStandardSequenceOperatorsTest.tearDown(); }),
("testSingle_DecrementCountsFirst", { _ObservableStandardSequenceOperatorsTest.setUp(); _ObservableStandardSequenceOperatorsTest.testSingle_DecrementCountsFirst(); _ObservableStandardSequenceOperatorsTest.tearDown(); }),
("testSinglePredicate_Empty", { _ObservableStandardSequenceOperatorsTest.setUp(); _ObservableStandardSequenceOperatorsTest.testSinglePredicate_Empty(); _ObservableStandardSequenceOperatorsTest.tearDown(); }),
("testSinglePredicate_One", { _ObservableStandardSequenceOperatorsTest.setUp(); _ObservableStandardSequenceOperatorsTest.testSinglePredicate_One(); _ObservableStandardSequenceOperatorsTest.tearDown(); }),
("testSinglePredicate_Many", { _ObservableStandardSequenceOperatorsTest.setUp(); _ObservableStandardSequenceOperatorsTest.testSinglePredicate_Many(); _ObservableStandardSequenceOperatorsTest.tearDown(); }),
//("testSinglePredicate_Error", { _ObservableStandardSequenceOperatorsTest.setUp(); _ObservableStandardSequenceOperatorsTest.testSinglePredicate_Error(); _ObservableStandardSequenceOperatorsTest.tearDown(); }),
//("testSinglePredicate_Throws", { _ObservableStandardSequenceOperatorsTest.setUp(); _ObservableStandardSequenceOperatorsTest.testSinglePredicate_Throws(); _ObservableStandardSequenceOperatorsTest.tearDown(); }),
("testSinglePredicate_DecrementCountsFirst", { _ObservableStandardSequenceOperatorsTest.setUp(); _ObservableStandardSequenceOperatorsTest.testSinglePredicate_DecrementCountsFirst(); _ObservableStandardSequenceOperatorsTest.tearDown(); }),
]

View File

@ -287,6 +287,23 @@ extension ControlTests {
}
}
// UIProgressView
extension ControlTests {
func testProgressView_HasWeakReference() {
ensureControlObserverHasWeakReference(UIProgressView(), { (progressView: UIProgressView) -> AnyObserver<Float> in progressView.rx_progress }, { Variable<Float>(0.0).asObservable() })
}
func testProgressView_NextElementsSetsValue() {
let subject = UIProgressView()
let progressSequence = Variable<Float>(0.0)
let disposable = progressSequence.asObservable().bindTo(subject.rx_progress)
defer { disposable.dispose() }
progressSequence.value = 1.0
XCTAssert(subject.progress == progressSequence.value, "Expected progress to have been set")
}
}
// UITableView
extension ControlTests {
func testTableView_DelegateEventCompletesOnDealloc() {
@ -614,15 +631,6 @@ extension ControlTests {
}
}
// UISearchBar
extension ControlTests {
func testSearchBar_DelegateEventCompletesOnDealloc() {
let createView: () -> UISearchBar = { UISearchBar(frame: CGRectMake(0, 0, 1, 1)) }
ensurePropertyDeallocated(createView, "a") { (view: UISearchBar) in view.rx_text }
}
}
// UIButton
extension ControlTests {
func testButton_tapDeallocates() {

View File

@ -13,89 +13,4 @@ import XCTest
class ControlTests : RxTest {
func ensurePropertyDeallocated<C, T: Equatable where C: NSObject>(createControl: () -> C, _ initialValue: T, _ propertySelector: C -> ControlProperty<T>) {
let variable = Variable(initialValue)
var completed = false
var deallocated = false
var lastReturnedPropertyValue: T!
autoreleasepool {
var control: C! = createControl()
let property = propertySelector(control)
let disposable = variable.asObservable().bindTo(property)
_ = property.subscribe(onNext: { n in
lastReturnedPropertyValue = n
}, onCompleted: {
completed = true
disposable.dispose()
})
_ = control.rx_deallocated.subscribeNext { _ in
deallocated = true
}
control = nil
}
XCTAssertTrue(deallocated)
XCTAssertTrue(completed)
XCTAssertEqual(initialValue, lastReturnedPropertyValue)
}
func ensureEventDeallocated<C, T where C: NSObject>(createControl: () -> C, _ eventSelector: C -> ControlEvent<T>) {
return ensureEventDeallocated({ () -> (C, Disposable) in (createControl(), NopDisposable.instance) }, eventSelector)
}
func ensureEventDeallocated<C, T where C: NSObject>(createControl: () -> (C, Disposable), _ eventSelector: C -> ControlEvent<T>) {
var completed = false
var deallocated = false
let outerDisposable = SingleAssignmentDisposable()
autoreleasepool {
let (control, disposable) = createControl()
let eventObservable = eventSelector(control)
_ = eventObservable.subscribe(onNext: { n in
}, onCompleted: {
completed = true
})
_ = control.rx_deallocated.subscribeNext { _ in
deallocated = true
}
outerDisposable.disposable = disposable
}
outerDisposable.dispose()
XCTAssertTrue(deallocated)
XCTAssertTrue(completed)
}
func ensureControlObserverHasWeakReference<C, T where C: NSObject>(@autoclosure createControl: () -> (C), _ observerSelector: C -> AnyObserver<T>, _ observableSelector: () -> (Observable<T>)) {
var deallocated = false
let disposeBag = DisposeBag()
autoreleasepool {
let control = createControl()
let propertyObserver = observerSelector(control)
let observable = observableSelector()
observable.bindTo(propertyObserver).addDisposableTo(disposeBag)
_ = control.rx_deallocated.subscribeNext { _ in
deallocated = true
}
}
XCTAssertTrue(deallocated)
}
}

View File

@ -280,9 +280,7 @@ class ThreeDSectionedViewDelegateProxy : DelegateProxy
extension ThreeDSectionedView {
var rx_proxy: DelegateProxy {
get {
return proxyForObject(ThreeDSectionedViewDelegateProxy.self, self)
}
return proxyForObject(ThreeDSectionedViewDelegateProxy.self, self)
}
}

View File

@ -0,0 +1,111 @@
//
// RxTest+Controls.swift
// Rx
//
// Created by Krunoslav Zaher on 3/12/16.
// Copyright © 2016 Krunoslav Zaher. All rights reserved.
//
import Foundation
import RxCocoa
import RxSwift
import XCTest
extension RxTest {
func ensurePropertyDeallocated<C, T: Equatable where C: NSObject>(createControl: () -> C, _ initialValue: T, _ propertySelector: C -> ControlProperty<T>) {
let variable = Variable(initialValue)
var completed = false
var deallocated = false
var lastReturnedPropertyValue: T!
autoreleasepool {
var control: C! = createControl()
let property = propertySelector(control)
let disposable = variable.asObservable().bindTo(property)
_ = property.subscribe(onNext: { n in
lastReturnedPropertyValue = n
}, onCompleted: {
completed = true
disposable.dispose()
})
_ = control.rx_deallocated.subscribeNext { _ in
deallocated = true
}
control = nil
}
// this code is here to flush any events that were scheduled to
// run on main loop
dispatch_async(dispatch_get_main_queue()) {
let runLoop = CFRunLoopGetCurrent()
CFRunLoopStop(runLoop)
}
let runLoop = CFRunLoopGetCurrent()
CFRunLoopWakeUp(runLoop)
CFRunLoopRun()
XCTAssertTrue(deallocated)
XCTAssertTrue(completed)
XCTAssertEqual(initialValue, lastReturnedPropertyValue)
}
func ensureEventDeallocated<C, T where C: NSObject>(createControl: () -> C, _ eventSelector: C -> ControlEvent<T>) {
return ensureEventDeallocated({ () -> (C, Disposable) in (createControl(), NopDisposable.instance) }, eventSelector)
}
func ensureEventDeallocated<C, T where C: NSObject>(createControl: () -> (C, Disposable), _ eventSelector: C -> ControlEvent<T>) {
var completed = false
var deallocated = false
let outerDisposable = SingleAssignmentDisposable()
autoreleasepool {
let (control, disposable) = createControl()
let eventObservable = eventSelector(control)
_ = eventObservable.subscribe(onNext: { n in
}, onCompleted: {
completed = true
})
_ = control.rx_deallocated.subscribeNext { _ in
deallocated = true
}
outerDisposable.disposable = disposable
}
outerDisposable.dispose()
XCTAssertTrue(deallocated)
XCTAssertTrue(completed)
}
func ensureControlObserverHasWeakReference<C, T where C: NSObject>(@autoclosure createControl: () -> (C), _ observerSelector: C -> AnyObserver<T>, _ observableSelector: () -> (Observable<T>)) {
var deallocated = false
let disposeBag = DisposeBag()
autoreleasepool {
let control = createControl()
let propertyObserver = observerSelector(control)
let observable = observableSelector()
observable.bindTo(propertyObserver).addDisposableTo(disposeBag)
_ = control.rx_deallocated.subscribeNext { _ in
deallocated = true
}
}
XCTAssertTrue(deallocated)
}
}

View File

@ -0,0 +1,47 @@
//
// UISearchBar+RxTests.swift
// Rx
//
// Created by Krunoslav Zaher on 3/12/16.
// Copyright © 2016 Krunoslav Zaher. All rights reserved.
//
import Foundation
import RxSwift
import RxCocoa
import UIKit
import XCTest
class UISearchBarTests : RxTest {
func testText_completesOnDealloc() {
let createView: () -> UISearchBar = { UISearchBar(frame: CGRectMake(0, 0, 1, 1)) }
ensurePropertyDeallocated(createView, "a") { (view: UISearchBar) in view.rx_text }
}
func testText_changeEventWorks() {
let searchBar = UISearchBar(frame: CGRectMake(0, 0, 1, 1))
var latestText: String! = nil
// search bar should dispose this itself
_ = searchBar.rx_text.subscribeNext { text in
latestText = text
}
XCTAssertEqual(latestText, "")
searchBar.text = "newValue"
searchBar.delegate!.searchBar!(searchBar, textDidChange: "newValue")
XCTAssertEqual(latestText, "newValue")
}
func textText_binding() {
let searchBar = UISearchBar(frame: CGRectMake(0, 0, 1, 1))
XCTAssertNotEqual(searchBar.text, "value")
_ = Observable.just("value").bindTo(searchBar.rx_text)
XCTAssertEqual(searchBar.text, "value")
}
}

View File

@ -0,0 +1,33 @@
//
// UITabBarItem+RxTests.swift
// Rx
//
// Created by Mateusz Derks on 04/03/16.
// Copyright © 2016 Krunoslav Zaher. All rights reserved.
//
import Foundation
import RxSwift
import RxCocoa
import UIKit
import XCTest
class UITabBarItemTests : RxTest {
}
extension UITabBarItemTests {
func testBadgetValue_Text() {
let subject = UITabBarItem(tabBarSystemItem: .More, tag: 0)
Observable.just("5").subscribe(subject.rx_badgeValue).dispose()
XCTAssertTrue(subject.badgeValue == "5")
}
func testBadgetValue_Empty() {
let subject = UITabBarItem(tabBarSystemItem: .More, tag: 0)
Observable.just(nil).subscribe(subject.rx_badgeValue).dispose()
XCTAssertTrue(subject.badgeValue == nil)
}
}

View File

@ -19,15 +19,11 @@ class MySubject<Element where Element : Hashable> : SubjectType, ObserverType {
var _disposed: Bool = false
var subscribeCount: Int {
get {
return _subscribeCount
}
return _subscribeCount
}
var diposed: Bool {
get {
return _disposed
}
return _disposed
}
func disposeOn(value: Element, disposable: Disposable) {

View File

@ -5067,6 +5067,14 @@ extension ObservableStandardSequenceOperatorsTest {
Subscription(200, 210)
])
}
func testSingle_DecrementCountsFirst() {
let k = BehaviorSubject(value: false)
_ = k.single { _ in true }.subscribeNext { n in
k.on(.Next(!n))
}
}
func testSinglePredicate_Empty() {
let scheduler = TestScheduler(initialClock: 0)
@ -5199,5 +5207,14 @@ extension ObservableStandardSequenceOperatorsTest {
Subscription(200, 230)
])
}
func testSinglePredicate_DecrementCountsFirst() {
let k = BehaviorSubject(value: false)
_ = k.single { _ in true }.subscribeNext { n in
k.on(.Next(!n))
}
}
}

View File

@ -36,9 +36,7 @@ class RxTest
private var startResourceCount: Int32 = 0
var accumulateStatistics: Bool {
get {
return true
}
return true
}
#if TRACE_RESOURCES