Update RXCocoa

And some work on RXCocoasamples.
This commit is contained in:
Seivan Heidari 2015-07-06 08:35:19 +02:00 committed by Krunoslav Zaher
parent 8c87a92326
commit 09cdeca380
81 changed files with 440 additions and 435 deletions

View File

@ -25,11 +25,11 @@ example("Empty observable") {
let emptySubscriber = emptyObservable >- subscribe { event in
switch event {
case .Next(let box):
println("\(box.value)")
print("\(box.value)")
case .Completed:
println("completed")
print("completed")
case .Error(let error):
println("\(error)")
print("\(error)")
}
}
}
@ -47,7 +47,7 @@ example("Never observable") {
let neverObservable: Observable<String> = never()
let neverSubscriber = neverObservable >- subscribe { _ in
println("This block is never called.")
print("This block is never called.")
}
}
@ -63,11 +63,11 @@ example("returnElement/just") {
>- subscribe { event in
switch event {
case .Next(let box):
println("\(box.value)")
print("\(box.value)")
case .Completed:
println("completed")
print("completed")
case .Error(let error):
println("\(error)")
print("\(error)")
}
}
}
@ -88,11 +88,11 @@ example("returnElements") {
>- subscribe { event in
switch event {
case .Next(let box):
println("\(box.value)")
print("\(box.value)")
case .Completed:
println("completed")
print("completed")
case .Error(let error):
println("\(error)")
print("\(error)")
}
}
}
@ -113,11 +113,11 @@ example("from") {
>- subscribe { event in
switch event {
case .Next(let box):
println("\(box.value)")
print("\(box.value)")
case .Completed:
println("completed")
print("completed")
case .Error(let error):
println("\(error)")
print("\(error)")
}
}
}
@ -138,7 +138,7 @@ Up to this point, I have only used the `subscribe` method to listen to Observabl
example("subscribeNext") {
let nextOnlySubscriber = returnElements(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
>- subscribeNext { value in
println("\(value)")
print("\(value)")
}
}
@ -162,7 +162,7 @@ example("filter") {
$0 % 2 == 0
}
>- subscribeNext { value in
println("\(value)")
print("\(value)")
}
}
@ -175,7 +175,7 @@ example("distinctUntilChanged") {
let distinctUntilChangedSubscriber = returnElements(1, 2, 3, 1, 1, 4)
>- distinctUntilChanged
>- subscribeNext { value in
println("\(value)")
print("\(value)")
}
}
@ -196,7 +196,7 @@ example("aggregate") {
let aggregateSubscriber = returnElements(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
>- aggregate(0, +)
>- subscribeNext { value in
println("\(value)")
print("\(value)")
}
}

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='5.0' target-platform='osx'>
<playground version='5.0' target-platform='osx' requires-full-environment='true'>
<timeline fileName='timeline.xctimeline'/>
</playground>

View File

@ -22,12 +22,13 @@ example("startWith") {
>- startWith(1)
>- startWith(0)
>- subscribeNext { int in
println(int)
print(int)
}
}
/*:
e/*:
### `combineLatest`
Takes several source Obserbables and a closure as parameters, returns an Observable which emits the latest items of each source Obsevable, procesed through the closure.
@ -36,8 +37,7 @@ Once each source Observables have each emitted an item, `combineLatest` emits an
The next example shows how
*/
example("combineLatest 1st") {
xample("combineLatest 1st") {
let intOb1 = PublishSubject<String>()
let intOb2 = PublishSubject<Int>()
@ -45,31 +45,31 @@ example("combineLatest 1st") {
"\($0) \($1)"
}
>- subscribeNext {
println($0)
print($0)
}
println("send A to first channel")
print("send A to first channel")
sendNext(intOb1, "A")
println("note that nothing outputs")
print("note that nothing outputs")
println("\nsend 1 to second channel")
print("\nsend 1 to second channel")
sendNext(intOb2, 1)
println("now that there is something in both channels, there is output")
print("now that there is something in both channels, there is output")
println("\nsend B to first channel")
print("\nsend B to first channel")
sendNext(intOb1, "B")
println("now that both channels are full, whenever either channel emits a value, the combined channel also emits a value")
print("now that both channels are full, whenever either channel emits a value, the combined channel also emits a value")
println("\nsend 2 to second channel")
print("\nsend 2 to second channel")
sendNext(intOb2, 2)
println("note that the combined channel emits a value whenever either sub-channel emits a value, even if the value is the same")
print("note that the combined channel emits a value whenever either sub-channel emits a value, even if the value is the same")
}
//: This example show once in each channel there are output for each new channel output the resulting observable also produces an output
example("combineLatest 2nd") {
example("combineLat//: This example show once in each channel there are output for each new channel output the resulting observable also produces an output
est 2nd") {
let intOb1 = just(2)
let intOb2 = from([0, 1, 2, 3, 4])
@ -77,16 +77,16 @@ example("combineLatest 2nd") {
$0 * $1
}
>- subscribeNext {
println($0)
print($0)
}
}
/*:
example("combineLates/*:
There are a serie of functions `combineLatest`, they take from two to ten sources Obserbables and the closure
The next sample shows combineLatest called with three sorce Observables
*/
example("combineLatest 3rd") {
t 3rd") {
let intOb1 = just(2)
let intOb2 = from([0, 1, 2, 3])
let intOb3 = from([0, 1, 2, 3, 4])
@ -95,74 +95,74 @@ example("combineLatest 3rd") {
($0 + $1) * $2
}
>- subscribeNext {
println($0)
print($0)
}
}
/*:
example("zip 1st") {
/*:
### `zip`
Takes several source Observables and a closure as parameters, returns an Observable which emit the items of the second Obsevable procesed, through the closure, with the last item of first Observable
The Observable returned by `zip` emits an item only when all of the imputs Observables have emited an item
[More info in reactive.io website](http://reactivex.io/documentation/operators/zip.html)
*/
example("zip 1st") {
let intOb1 = PublishSubject<String>()
let intOb1 = PublishSubject<String>()
let intOb2 = PublishSubject<Int>()
zip(intOb1, intOb2) {
"\($0) \($1)"
}
>- subscribeNext {
println($0)
print($0)
}
println("send A to first channel")
print("send A to first channel")
sendNext(intOb1, "A")
println("note that nothing outputs")
print("note that nothing outputs")
println("\nsend 1 to second channel")
print("\nsend 1 to second channel")
sendNext(intOb2, 1)
println("now that both source channels have output, there is output")
print("now that both source channels have output, there is output")
println("\nsend B to first channel")
print("\nsend B to first channel")
sendNext(intOb1, "B")
println("note that nothing outputs, since channel 1 has two outputs but channel 2 only has one")
print("note that nothing outputs, since channel 1 has two outputs but channel 2 only has one")
println("\nsend C to first channel")
print("\nsend C to first channel")
sendNext(intOb1, "C")
println("note that nothing outputs, it is the same as in the previous step, since channel 1 has three outputs but channel 2 only has one")
print("note that nothing outputs, it is the same as in the previous step, since channel 1 has three outputs but channel 2 only has one")
println("\nsend 2 to second channel")
print("\nsend 2 to second channel")
sendNext(intOb2, 2)
println("note that the combined channel emits a value with the second output of each channel")
print("note that the combined channel emits a value with the second output of each channel")
}
//: This example show once in each channel there are output for each new channel output the resulting observable also produces an output
example("zip 2nd") {
let intOb1 = just(2)
let intOb1 = just(2)//: This example show once in each channel there are output for each new channel output the resulting observable also produces an output
let intOb2 = from([0, 1, 2, 3, 4])
zip(intOb1, intOb2) {
$0 * $1
}
>- subscribeNext {
println($0)
print($0)
}
}
/*:
example("zip 3rd") {
let intOb1 = from([0, /*:
There are a serie of functions `zip`, they take from two to ten sources Obserbables and the closure
The next sample shows zip called with three sorce Observables
*/
example("zip 3rd") {
let intOb1 = from([0, 1])
1])
let intOb2 = from([0, 1, 2, 3])
let intOb3 = from([0, 1, 2, 3, 4])
@ -170,26 +170,26 @@ example("zip 3rd") {
($0 + $1) * $2
}
>- subscribeNext {
println($0)
print($0)
}
}
/*:
example("merge 1st") {
let subject1 = Publish/*:
### `merge`
Combine multiple Observables, of the same type, into one by merging their emissions
[More info in reactive.io website]( http://reactivex.io/documentation/operators/merge.html )
*/
example("merge 1st") {
let subject1 = PublishSubject<Int>()
Subject<Int>()
let subject2 = PublishSubject<Int>()
merge(returnElements(subject1, subject2))
>- subscribeNext { int in
println(int)
print(int)
}
sendNext(subject1, 20)
@ -209,7 +209,7 @@ example("merge 2nd") {
returnElements(subject1, subject2)
>- merge(maxConcurrent: 2)
>- subscribeNext { int in
println(int)
print(int)
}
sendNext(subject1, 20)
@ -222,16 +222,16 @@ example("merge 2nd") {
}
/*:
example("switchLatest") {
let var1 = Variable(0)/*:
### `switchLatest`
Convert an Observable that emits Observables into a single Observable that emits the items emitted by the most-recently-emitted of those Observables.
[More info in reactive.io website]( http://reactivex.io/documentation/operators/switch.html )
*/
example("switchLatest") {
let var1 = Variable(0)
let var2 = Variable(200)
// var3 is like an Observable<Observable<Int>>
@ -240,7 +240,7 @@ example("switchLatest") {
let d = var3
>- switchLatest
>- subscribeNext { (e: Int) -> Void in
println("\(e)")
print("\(e)")
}
var1.next(1)
@ -252,7 +252,7 @@ example("switchLatest") {
var2.next(201)
println("Note which no listen to var1")
print("Note which no listen to var1")
var1.next(5)
var1.next(6)
var1.next(7)

View File

@ -1,6 +1,6 @@
public func example(description: String, action: () -> ()) {
println("\n--- \(description) example ---")
print("\n--- \(description) example ---")
action()
}

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='5.0' target-platform='osx' display-mode='rendered'>
<playground version='5.0' target-platform='osx' requires-full-environment='true' display-mode='rendered'>
<timeline fileName='timeline.xctimeline'/>
</playground>

View File

@ -22,7 +22,7 @@ example("takeUntil") {
observable1
>- takeUntil(observable2)
>- subscribeNext { int in
println(int)
print(int)
}
sendNext(observable1, 1)
@ -36,7 +36,8 @@ example("takeUntil") {
}
/*:
e/*:
### `takeWhile`
@ -44,8 +45,7 @@ example("takeUntil") {
Mirror items emitted by an Observable until a specified condition becomes false
[More info in reactive.io website]( http://reactivex.io/documentation/operators/takewhile.html )
*/
example("takeWhile") {
xample("takeWhile") {
let observable1 = PublishSubject<Int>()
@ -54,7 +54,7 @@ example("takeWhile") {
int < 4
}
>- subscribeNext { int in
println(int)
print(int)
}
sendNext(observable1, 1)

View File

@ -1,6 +1,6 @@
public func example(description: String, action: () -> ()) {
println("\n--- \(description) example ---")
print("\n--- \(description) example ---")
action()
}

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='5.0' target-platform='osx' display-mode='rendered'>
<playground version='5.0' target-platform='osx' requires-full-environment='true' display-mode='rendered'>
<timeline fileName='timeline.xctimeline'/>
</playground>

View File

@ -16,13 +16,13 @@ func sampleWithoutConnectableOperators() {
int1
>- subscribeNext {
println("first subscription \($0)")
print("first subscription \($0)")
}
delay(5) {
int1
>- subscribeNext {
println("second subscription \($0)")
print("second subscription \($0)")
}
}
@ -30,19 +30,19 @@ func sampleWithoutConnectableOperators() {
sampleWithoutConnectableOperators()
/*:
fu/*:
### `multicast`
[More info in reactive.io website]( http://reactivex.io/documentation/operators/publish.html )
*/
func sampleWithMulticast() {
nc sampleWithMulticast() {
let subject1 = PublishSubject<Int64>()
subject1
>- subscribeNext {
println("Subject \($0)")
print("Subject \($0)")
}
let int1 = interval(1, MainScheduler.sharedInstance)
@ -50,7 +50,7 @@ func sampleWithMulticast() {
int1
>- subscribeNext {
println("first subscription \($0)")
print("first subscription \($0)")
}
delay(2) {
@ -60,15 +60,15 @@ func sampleWithMulticast() {
delay(4) {
int1
>- subscribeNext {
println("second subscription \($0)")
println("---")
print("second subscription \($0)")
print("---")
}
}
delay(6) {
int1
>- subscribeNext {
println("thirth subscription \($0)")
print("thirth subscription \($0)")
}
}
@ -78,7 +78,9 @@ func sampleWithMulticast() {
/*:
func sampleW/*:
### `replay`
Ensure that all observers see the same sequence of emitted items, even if they subscribe after the Observable has begun emitting items.
@ -87,16 +89,14 @@ publish = multicast + replay subject
[More info in reactive.io website]( http://reactivex.io/documentation/operators/replay.html )
*/
func sampleWithReplayBuffer0() {
ithReplayBuffer0() {
let int1 = interval(1, MainScheduler.sharedInstance)
>- replay(0)
int1
>- subscribeNext {
println("first subscription \($0)")
print("first subscription \($0)")
}
delay(2) {
@ -106,15 +106,15 @@ func sampleWithReplayBuffer0() {
delay(4) {
int1
>- subscribeNext {
println("second subscription \($0)")
println("---")
print("second subscription \($0)")
print("---")
}
}
delay(6) {
int1
>- subscribeNext {
println("thirth subscription \($0)")
print("thirth subscription \($0)")
}
}
@ -125,14 +125,14 @@ func sampleWithReplayBuffer0() {
func sampleWithReplayBuffer2() {
println("--- sampleWithReplayBuffer2 ---\n")
print("--- sampleWithReplayBuffer2 ---\n")
let int1 = interval(1, MainScheduler.sharedInstance)
>- replay(2)
int1
>- subscribeNext {
println("first subscription \($0)")
print("first subscription \($0)")
}
delay(2) {
@ -142,15 +142,15 @@ func sampleWithReplayBuffer2() {
delay(4) {
int1
>- subscribeNext {
println("second subscription \($0)")
println("---")
print("second subscription \($0)")
print("---")
}
}
delay(6) {
int1
>- subscribeNext {
println("third subscription \($0)")
print("third subscription \($0)")
}
}
@ -160,7 +160,10 @@ func sampleWithReplayBuffer2() {
/*:
func sampleWithPublish() {
/*:
### `publish`
Convert an ordinary Observable into a connectable Observable.
@ -170,16 +173,13 @@ so publish is basically replay(0)
[More info in reactive.io website]( http://reactivex.io/documentation/operators/publish.html )
*/
func sampleWithPublish() {
let int1 = interval(1, MainScheduler.sharedInstance)
>- publish
int1
>- subscribeNext {
println("first subscription \($0)")
print("first subscription \($0)")
}
delay(2) {
@ -189,15 +189,15 @@ func sampleWithPublish() {
delay(4) {
int1
>- subscribeNext {
println("second subscription \($0)")
println("---")
print("second subscription \($0)")
print("---")
}
}
delay(6) {
int1
>- subscribeNext {
println("third subscription \($0)")
print("third subscription \($0)")
}
}
@ -206,18 +206,18 @@ func sampleWithPublish() {
//sampleWithPublish()
/*:
XCPSetExecutionShouldContinueIndefi/*:
### `refCount`
Make a Connectable Observable behave like an ordinary Observable.
[More info in reactive.io website]( http://reactivex.io/documentation/operators/refcount.html )
*/
/*:
nit/*:
### `Variable` / `sharedWithCachedLastResult`
*/
XCPSetExecutionShouldContinueIndefinitely(continueIndefinitely: true)
ely(continueIndefinitely: true)

View File

@ -1,7 +1,7 @@
public func example(description: String, action: () -> ()) {
println("\n--- \(description) example ---")
print("\n--- \(description) example ---")
action()
}

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='5.0' target-platform='osx' auto-termination-delay='11' display-mode='rendered'>
<playground version='5.0' target-platform='osx' auto-termination-delay='11' requires-full-environment='true' display-mode='rendered'>
<timeline fileName='timeline.xctimeline'/>
</playground>

View File

@ -19,16 +19,16 @@ example("Empty observable") {
let emptySubscriber = emptyObservable >- subscribe { event in
switch event {
case .Next(let box):
println("\(box.value)")
print("\(box.value)")
case .Completed:
println("completed")
print("completed")
case .Error(let error):
println("\(error)")
print("\(error)")
}
}
}
/*:
exampl/*:
As you can see, no values are ever sent to the subscriber of an empty observable. It just completes and is done.
@ -38,24 +38,24 @@ As you can see, no values are ever sent to the subscriber of an empty observable
Creates an observable that contains no objects and never completes or errors out.
[More info in reactive.io website]( http://reactivex.io/documentation/operators/empty-never-throw.html )
*/
example("Never observable") {
e("Never observable") {
let neverObservable: Observable<String> = never()
let neverSubscriber = neverObservable
>- subscribe { _ in
println("This block is never called.")
print("This block is never called.")
}
}
/*:
example/*:
### `failWith`
Creates an observable that contains no objects and send only a error out.
[More info in reactive.io website]( http://reactivex.io/documentation/operators/empty-never-throw.html )
*/
example("failWith") {
("failWith") {
let error = NSError(domain: "Test", code: -1, userInfo: nil)
let errorObservable: Observable<Int> = failWith(error)
@ -64,39 +64,40 @@ example("failWith") {
>- subscribe { event in
switch event {
case .Next(let box):
println("\(box.value)")
print("\(box.value)")
case .Completed:
println("completed")
print("completed")
case .Error(let error):
println("\(error)")
print("\(error)")
}
}
}
/*:
example("retu/*:
### `returnElement` / `just`
These two functions behave identically. They send two messages to subscribers. The first message is the value and the second message is `.Complete`.
[More info in reactive.io website]( http://reactivex.io/documentation/operators/just.html )
*/
example("returnElement/just") {
rnElement/just") {
let oneObservable = just(32)
let oneObservableSubscriber = oneObservable
>- subscribe { event in
switch event {
case .Next(let box):
println("\(box.value)")
print("\(box.value)")
case .Completed:
println("completed")
print("completed")
case .Error(let error):
println("\(error)")
print("\(error)")
}
}
}
/*:
example("returnElem/*:
Here we see that the `.Next` event is sent just once, then the `.Completed` event is sent.
@ -105,24 +106,25 @@ Here we see that the `.Next` event is sent just once, then the `.Completed` even
Now we are getting to some more interesting ways to create an Observable. This function creates an observable that produces a number of values before completing.
*/
example("returnElements") {
ents") {
let multipleObservable/* : Observable<Int> */ = returnElements(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
let multipleObservableSubscriber = multipleObservable
>- subscribe { event in
switch event {
case .Next(let box):
println("\(box.value)")
print("\(box.value)")
case .Completed:
println("completed")
print("completed")
case .Error(let error):
println("\(error)")
print("\(error)")
}
}
}
/*:
example("from") {
let/*:
With the above, you will see that the `.Next` event was sent ten times, once for each element. Then `.Complete` was sent.
@ -131,35 +133,33 @@ With the above, you will see that the `.Next` event was sent ten times, once for
We can also create an observable from any SequenceType, such as an array
[More info in reactive.io website]( http://reactivex.io/documentation/operators/from.html )
*/
example("from") {
let fromArrayObservable = from([1, 2, 3, 4, 5])
fromArrayObservable = from([1, 2, 3, 4, 5])
let fromArrayObservableSubscriber = fromArrayObservable
>- subscribe { event in
switch event {
case .Next(let box):
println("\(box.value)")
print("\(box.value)")
case .Completed:
println("completed")
print("completed")
case .Error(let error):
println("\(error)")
print("\(error)")
}
}
}
/*:
example("create") {
pr/*:
### `create`
Create an Observable from scratch by means of a function
[More info in reactive.io website]( http://reactivex.io/documentation/operators/create.html )
*/
example("create") {
println("creating")
int("creating")
let observable: Observable<Int> = create { observer in
println("emmiting")
print("emmiting")
sendNext(observer, 0)
sendNext(observer, 1)
sendNext(observer, 2)
@ -169,28 +169,28 @@ example("create") {
observable
>- subscribeNext {
println($0)
print($0)
}
observable
>- subscribeNext {
println($0)
print($0)
}
}
/*:
example("defer") {
let defered/*:
### `defer`
Create an Observable from a function which create an observable. But do not create the Observable until the observer subscribes, and create a fresh Observable for each observer
[More info in reactive.io website]( http://reactivex.io/documentation/operators/defer.html )
*/
example("defer") {
let defered: Observable<Int> = defer {
println("creating")
: Observable<Int> = defer {
print("creating")
return create { observer in
println("emmiting")
print("emmiting")
sendNext(observer, 0)
sendNext(observer, 1)
sendNext(observer, 2)
@ -201,12 +201,12 @@ example("defer") {
defered
>- subscribeNext {
println($0)
print($0)
}
defered
>- subscribeNext {
println($0)
print($0)
}
}

View File

@ -1,6 +1,6 @@
public func example(description: String, action: () -> ()) {
println("\n--- \(description) example ---")
print("\n--- \(description) example ---")
action()
}

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='5.0' target-platform='osx' display-mode='rendered'>
<playground version='5.0' target-platform='osx' requires-full-environment='true' display-mode='rendered'>
<timeline fileName='timeline.xctimeline'/>
</playground>

View File

@ -27,11 +27,11 @@ example("catch 1st") {
>- subscribe { event in
switch event {
case .Next(let box):
println("\(box.value)")
print("\(box.value)")
case .Completed:
println("completed")
print("completed")
case .Error(let error):
println("\(error)")
print("\(error)")
}
}
@ -60,11 +60,11 @@ example("catch 2nd") {
>- subscribe { event in
switch event {
case .Next(let box):
println("\(box.value)")
print("\(box.value)")
case .Completed:
println("completed")
print("completed")
case .Error(let error):
println("\(error)")
print("\(error)")
}
}
@ -79,14 +79,14 @@ example("catch 2nd") {
}
/*:
example("re/*:
### `retry`
If a source Observable emits an error, resubscribe to it in the hopes that it will complete without error
[More info in reactive.io website]( http://reactivex.io/documentation/operators/retry.html )
*/
example("retry") {
try") {
var count = 1 // bad practice, only for example purposes
let observable: Observable<Int> = create { observer in
@ -111,11 +111,11 @@ example("retry") {
>- subscribe { event in
switch event {
case .Next(let box):
println("\(box.value)")
print("\(box.value)")
case .Completed:
println("completed")
print("completed")
case .Error(let error):
println("\(error)")
print("\(error)")
}
}
}

View File

@ -1,6 +1,6 @@
public func example(description: String, action: () -> ()) {
println("\n--- \(description) example ---")
print("\n--- \(description) example ---")
action()
}

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='5.0' target-platform='osx' display-mode='rendered'>
<playground version='5.0' target-platform='osx' requires-full-environment='true' display-mode='rendered'>
<timeline fileName='timeline.xctimeline'/>
</playground>

View File

@ -21,37 +21,37 @@ example("filter") {
$0 % 2 == 0
}
>- subscribeNext { value in
println("\(value)")
print("\(value)")
}
}
/*:
e/*:
### `distinctUntilChanged`
suppress duplicate items emitted by an Observable
[More info in reactive.io website]( http://reactivex.io/documentation/operators/distinct.html )
*/
example("distinctUntilChanged") {
xample("distinctUntilChanged") {
let distinctUntilChangedSubscriber = returnElements(1, 2, 3, 1, 1, 4)
>- distinctUntilChanged
>- subscribeNext { value in
println("\(value)")
print("\(value)")
}
}
/*:
exa/*:
### `take`
Emit only the first n items emitted by an Observable
[More info in reactive.io website]( http://reactivex.io/documentation/operators/take.html )
*/
example("take") {
mple("take") {
let distinctUntilChangedSubscriber = returnElements(1, 2, 3, 4, 5, 6)
>- take(3)
>- subscribeNext { value in
println("\(value)")
print("\(value)")
}
}

View File

@ -1,6 +1,6 @@
public func example(description: String, action: () -> ()) {
println("\n--- \(description) example ---")
print("\n--- \(description) example ---")
action()
}

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='5.0' target-platform='osx' display-mode='rendered'>
<playground version='5.0' target-platform='osx' requires-full-environment='true' display-mode='rendered'>
<timeline fileName='timeline.xctimeline'/>
</playground>

View File

@ -25,7 +25,7 @@ example("concat") {
let d = var3
>- concat
>- subscribeNext { (e: Int) -> Void in
println("\(e)")
print("\(e)")
}
var1.next(1)
@ -47,7 +47,8 @@ example("concat") {
var2.next(204)
}
/*:
e/*:
### `reduce` / `aggregate`
@ -57,11 +58,10 @@ This function will perform a function on each element in the sequence until it i
[More info in reactive.io website]( http://reactivex.io/documentation/operators/reduce.html )
*/
example("aggregate") {
xample("aggregate") {
let aggregateSubscriber = returnElements(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
>- aggregate(0, +)
>- subscribeNext { value in
println("\(value)")
print("\(value)")
}
}

View File

@ -1,6 +1,6 @@
public func example(description: String, action: () -> ()) {
println("\n--- \(description) example ---")
print("\n--- \(description) example ---")
action()
}

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='5.0' target-platform='osx' display-mode='rendered'>
<playground version='5.0' target-platform='osx' requires-full-environment='true' display-mode='rendered'>
<timeline fileName='timeline.xctimeline'/>
</playground>

View File

@ -29,18 +29,18 @@ example("map") {
char.hashValue
}
>- subscribeNext { int in
println(int)
print(int)
}
}
/*:
e/*:
### `flatMap`
Transform the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable
[More info in reactive.io website]( http://reactivex.io/documentation/operators/flatmap.html )
*/
example("flatMap") {
xample("flatMap") {
let observable1: Observable<Int> = create { observer in
sendNext(observer, 1)
@ -66,18 +66,18 @@ example("flatMap") {
observable2
}
>- subscribeNext {
println($0)
print($0)
}
}
/*:
exa/*:
### `scan`
Apply a function to each item emitted by an Observable, sequentially, and emit each successive value
[More info in reactive.io website]( http://reactivex.io/documentation/operators/scan.html )
*/
example("scan") {
mple("scan") {
let observable: Observable<Int> = create { observer in
sendNext(observer, 0)
@ -95,6 +95,6 @@ example("scan") {
acum + elem
}
>- subscribeNext {
println($0)
print($0)
}
}

View File

@ -1,6 +1,6 @@
public func example(description: String, action: () -> ()) {
println("\n--- \(description) example ---")
print("\n--- \(description) example ---")
action()
}

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='5.0' target-platform='osx' display-mode='rendered'>
<playground version='5.0' target-platform='osx' requires-full-environment='true' display-mode='rendered'>
<timeline fileName='timeline.xctimeline'/>
</playground>

View File

@ -20,14 +20,15 @@ example("subscribe") {
intOb1
>- subscribe { event in
println(event)
print(event)
}
sendNext(intOb1, 1)
sendCompleted(intOb1)
}
/*:
e/*:
There are several variants of the `subscribe` operator. They works over one posible event type:
@ -36,59 +37,59 @@ There are several variants of the `subscribe` operator. They works over one posi
Create an Disposable which listen only Next event from source Observable, the given closure take the Even's value and is responsible for the actions to perform only when the Next even is produced.
*/
example("subscribeNext") {
xample("subscribeNext") {
let intOb1 = PublishSubject<Int>()
intOb1
>- subscribeNext { int in
println(int)
print(int)
}
sendNext(intOb1, 1)
sendCompleted(intOb1)
}
/*:
exa/*:
### `subscribeCompleted`
Create an Disposable which listen only Completed event from source Observable, the given closure take the Even's value and is responsible for the actions to perform only when the Completed even is produced.
*/
example("subscribeCompleted") {
mple("subscribeCompleted") {
let intOb1 = PublishSubject<Int>()
intOb1
>- subscribeCompleted {
println("It's completed")
print("It's completed")
}
sendNext(intOb1, 1)
sendCompleted(intOb1)
}
/*:
examp/*:
### `subscribeError
Create an Disposable which listen only Error event from source Observable, the given closure take the Even's value and is responsible for the actions to perform only when the Error even is produced
*/
example("subscribeError") {
le("subscribeError") {
let intOb1 = PublishSubject<Int>()
intOb1
>- subscribeError { error in
println(error)
print(error)
}
sendNext(intOb1, 1)
sendError(intOb1, NSError(domain: "Examples", code: -1, userInfo: nil))
}
/*:
example/*:
### `do`
@ -96,43 +97,42 @@ example("subscribeError") {
Returns the same source Observable but the given closure responsible for the actions to perform when the even is produced. The gived closure obtain the event produced by the source observable
[More info in reactive.io website]( http://reactivex.io/documentation/operators/do.html )
*/
example("do") {
("do") {
let intOb1 = PublishSubject<Int>()
let intOb2 = intOb1
>- `do` { event in
println("first \(event)")
print("first \(event)")
}
intOb2
>- subscribeNext { int in
println("second \(int)")
print("second \(int)")
}
sendNext(intOb1, 1)
}
/*:
example("do/*:
### `doOnNext`
It is a variant of the `do` operator. Returns the same source Observable but the given closure responsible for the actions to perform when the Next even is produced. The gived closure obtain the value of the Next event produced by the source observable.
[More info in reactive.io website]( http://reactivex.io/documentation/operators/do.html )
*/
example("doOnNext") {
OnNext") {
let intOb1 = PublishSubject<Int>()
let intOb2 = intOb1
>- doOnNext { int in
println("first \(int)")
print("first \(int)")
}
intOb2
>- subscribeNext { int in
println("second \(int)")
print("second \(int)")
}
sendNext(intOb1, 1)

View File

@ -1,6 +1,6 @@
public func example(description: String, action: () -> ()) {
println("\n--- \(description) example ---")
print("\n--- \(description) example ---")
action()
}

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='5.0' target-platform='osx' display-mode='rendered'>
<playground version='5.0' target-platform='osx' requires-full-environment='true' display-mode='rendered'>
<timeline fileName='timeline.xctimeline'/>
</playground>

View File

@ -21,7 +21,7 @@ RxSwift
├-RxBlocking - set of blocking operators for unit testing
├-RxExample - example apps: taste of Rx
└-Rx.xcworkspace - workspace that contains all of the projects hooked up
```
```
Hang out with us on [rxswift.slack.com](http://slack.rxswift.org) <img src="http://slack.rxswift.org/badge.svg">
@ -56,9 +56,9 @@ git diff | grep bug | less # linux pipes - programs communicate by sen
would become if written in RxSwift
```swift
gitDiff() >- grep("bug") >- less // rx pipe `>-` operator - rx units communicate by
gitDiff() >- grep("bug") >- less // rx pipe `>-` operator - rx units communicate by
// sending sequences of swift objects
// unfortunately `|` is reserved in swift
// unfortunately `|` is reserved in swift
// for logical or
```
@ -83,10 +83,10 @@ Here is an example of calculated variable:
let a = Variable(1)
let b = Variable(2)
combineLatest(a, b) { $0 + $1 }
>- filter { $0 >= 0 }
combineLatest(a, b) { $0 + $1 }
>- filter { $0 >= 0 }
>- map { "\($0) is positive" }
>- subscribeNext { println($0) } // prints: 3 is positive
>- subscribeNext { print($0) } // prints: 3 is positive
a.next(4) // prints: 6 is positive
@ -106,10 +106,10 @@ let a = Variable(1)
let b = Variable(2)
// immediately prints: 3 is positive
combineLatest(a, b) { $0 + $1 }
|> filter { $0 >= 0 }
combineLatest(a, b) { $0 + $1 }
|> filter { $0 >= 0 }
|> map { "\($0) is positive" }
|> subscribeNext { println($0) }
|> subscribeNext { print($0) }
// ...
```
@ -129,7 +129,7 @@ let subscription/*: Disposable */ = primeTextField.rx_text // type is Obser
>- concat // type is Observable<Prime>
>- map { "number \($0.n) is prime? \($0.isPrime)" } // type is Observable<String>
>- resultLabel.rx_subscribeTextTo // return Disposable that can be used to unbind everything
// This will set resultLabel.text to "number 43 is prime? true" after
// server call completes.
primeTextField.text = "43"
@ -167,7 +167,7 @@ self.usernameOutlet.rx_text >- map { username in
// Every user interface probably shows some state while async operation
// is executing.
// Let's assume that we want to show "Checking availability" while waiting for result.
// valid parameter can be
// valid parameter can be
// * true - is valid
// * false - not valid
// * nil - validation pending
@ -188,7 +188,7 @@ self.usernameOutlet.rx_text >- map { username in
}
// Since we now have `Observable<Observable<ValidationResult>>`
// we somehow need to return to normal `Observable` world.
// We could use `concat` operator from second example, but we really
// We could use `concat` operator from second example, but we really
// want to cancel pending asynchronous operation if new username is
// provided.
// That's what `switchLatest` does
@ -202,16 +202,15 @@ self.usernameOutlet.rx_text >- map { username in
errorLabel.textColor = validationColor(valid)
errorLabel.text = valid.message
}
// Why would we do it manually, that's tedious,
// Why would we do it manually, that's tedious,
// let's dispose everything automagically on view controller dealloc.
>- disposeBag.addDisposable
```
Can't get any simpler than this. There are more examples in the repository, so feel free to check them out.
Can't get any simpler than this. There are more examples in the repository, so feel free to check them out.
They include examples on how to use it in the context of MVVM pattern or without it.
## Build / Install / Run
Rx doesn't contain any external dependencies.
@ -431,7 +430,7 @@ There are two basic types of observables. In Rx both are represented by `Observa
Error handling is pretty straightforward. If one sequence terminates with error, then all of the dependent sequences will terminate with error. It's usual short circuit logic.
Unfortunately Swift doesn't have a concept of exceptions or some kind of built in error monad so this project introduces `RxResult` enum.
Unfortunately Swift doesn't have a concept of exceptions or some kind of built in error monad so this project introduces `RxResult` enum.
It is Swift port of Scala [`Try`](http://www.scala-lang.org/api/2.10.2/index.html#scala.util.Try) type. It is also similar to Haskell [`Either`](https://hackage.haskell.org/package/category-extras-0.52.0/docs/Control-Monad-Either.html) monad.
```
@ -450,7 +449,7 @@ result1.flatMap { okValue in // success handling block
}.recoverWith { error in // error handling block
// executed on error
return ?
}
}
```
## Naming conventions and best practices
@ -479,7 +478,7 @@ public func map<E, R>
Returning an error from a selector will cause entire graph of dependent sequence transformers to "die" and fail with error. Dying implies that it will release all of its resources and never produce another sequence value. This is usually not an obvious effect.
If there is some `UITextField` bound to a observable sequence that fails with error or completes, screen won't be updated ever again.
If there is some `UITextField` bound to a observable sequence that fails with error or completes, screen won't be updated ever again.
To make those situations more obvious, RxCocoa debug build will throw an exception in case some sequence that is bound to UI control terminates with an error.
@ -503,14 +502,14 @@ func >- <In, Out>(lhs: In, rhs: In -> Out) -> Out {
a >- b >- c is equivalent to c(b(a))
```
All of the Rx public interfaces don't depend at all on the `>-` operator.
All of the Rx public interfaces don't depend at all on the `>-` operator.
It was actually introduced quite late and you can use Rx operators (map, filter ...) without it.
It was actually introduced quite late and you can use Rx operators (map, filter ...) without it.
This is how Rx code would look like without `>-` operator
```
subscribeNext({ println($0) })(map({ "\($0) is positive" })(filter({ $0 >= 0 })(a)))
subscribeNext({ print($0) })(map({ "\($0) is positive" })(filter({ $0 >= 0 })(a)))
```
but it's highly unlikely that anybody would want to code like this, even though the code is technically correct, and will produce wanted results.
@ -525,7 +524,7 @@ public func |> <In, Out>(source: In, @noescape transform: In -> Out) -> Out {
}
```
or
or
```
infix operator ~> { associativity left precedence 91 }
@ -541,20 +540,20 @@ and you can use them instead of `>-` operator.
let a /*: Observable<Int>*/ = Variable(1)
let b /*: Observable<Int>*/ = Variable(2)
combineLatest(a, b) { $0 + $1 }
|> filter { $0 >= 0 }
combineLatest(a, b) { $0 + $1 }
|> filter { $0 >= 0 }
|> map { "\($0) is positive" }
|> subscribeNext { println($0) }
|> subscribeNext { print($0) }
```
```swift
let a /*: Observable<Int>*/ = Variable(1)
let b /*: Observable<Int>*/ = Variable(2)
combineLatest(a, b) { $0 + $1 }
~> filter { $0 >= 0 }
combineLatest(a, b) { $0 + $1 }
~> filter { $0 >= 0 }
~> map { "\($0) is positive" }
~> subscribeNext { println($0) }
~> subscribeNext { print($0) }
```
So why was `>-` chosen in the end? Well, it was a difficult decision.
@ -590,7 +589,7 @@ I have experimented for a week with different operators and in the end these are
## Peculiarities
* Swift support for generic enums is limited. That's why there is the `Box` hack in `Result` and `Event` enums
```
```
unimplemented IR generation feature non-fixed multi-payload enum layout
```
* Swift compiler had troubles with curried functions in release mode
@ -605,7 +604,7 @@ public func map<E, R> // this is ok
}
}
public func map<E, R> // this will cause crashes in release version
public func map<E, R> // this will cause crashes in release version
(selector: E -> R) // of your program if >- operator is used
(source: Observable<E>)
-> Observable<R> {

View File

@ -33,7 +33,7 @@ public class DelegateProxy : _RXDelegateProxy {
public func observe(selector: Selector) -> Observable<[AnyObject]> {
if hasWiredImplementationForSelector(selector) {
println("Delegate proxy is already implementing `\(selector)`, a more performant way of registering might exist.")
print("Delegate proxy is already implementing `\(selector)`, a more performant way of registering might exist.")
}
if !self.respondsToSelector(selector) {
@ -66,19 +66,19 @@ public class DelegateProxy : _RXDelegateProxy {
return _pointer(&delegateAssociatedTag)
}
public class func createProxyForObject(object: AnyObject) -> Self {
return self(parentObject: object)
public class func createProxyForObject(object: AnyObject) -> AnyObject {
return self.init(parentObject: object)
}
public class func assignedProxyFor(object: AnyObject) -> Self? {
let maybeDelegate: AnyObject! = objc_getAssociatedObject(object, self.delegateAssociatedObjectTag())
public class func assignedProxyFor(object: AnyObject) -> AnyObject? {
let maybeDelegate: AnyObject? = objc_getAssociatedObject(object, self.delegateAssociatedObjectTag())
return castOptionalOrFatalError(maybeDelegate)
}
public class func assignProxy(proxy: AnyObject, toObject object: AnyObject) {
precondition(proxy.isKindOfClass(self.classForCoder()))
objc_setAssociatedObject(object, self.delegateAssociatedObjectTag(), proxy, UInt(OBJC_ASSOCIATION_RETAIN))
objc_setAssociatedObject(object, self.delegateAssociatedObjectTag(), proxy, .OBJC_ASSOCIATION_RETAIN)
}
public func setForwardToDelegate(delegate: AnyObject?, retainDelegate: Bool) {

View File

@ -80,11 +80,11 @@ import RxSwift
//
public protocol DelegateProxyType : AnyObject {
// Creates new proxy for target object.
static func createProxyForObject(object: AnyObject) -> Self
static func createProxyForObject(object: AnyObject) -> AnyObject
// There can be only one registered proxy per object
// These functions control that.
static func assignedProxyFor(object: AnyObject) -> Self?
static func assignedProxyFor(object: AnyObject) -> AnyObject?
static func assignProxy(proxy: AnyObject, toObject object: AnyObject)
// Set/Get current delegate for object
@ -102,11 +102,11 @@ public protocol DelegateProxyType : AnyObject {
public func proxyForObject<P: DelegateProxyType>(object: AnyObject) -> P {
MainScheduler.ensureExecutingOnScheduler()
let maybeProxy = P.assignedProxyFor(object)
let maybeProxy = P.assignedProxyFor(object) as? P
let proxy: P
if maybeProxy == nil {
proxy = P.createProxyForObject(object)
proxy = P.createProxyForObject(object) as! P
P.assignProxy(proxy, toObject: object)
assert(P.assignedProxyFor(object) === proxy)
}
@ -155,7 +155,7 @@ func setProxyDataSourceForObject<P: DelegateProxyType, Element>(object: AnyObjec
-> Observable<Element> -> Disposable {
return { source in
let proxy: P = proxyForObject(object)
let disposable = installDelegate(proxy, dataSource, retainDataSource, onProxyForObject: object)
let disposable = installDelegate(proxy, delegate: dataSource, retainDelegate: retainDataSource, onProxyForObject: object)
// we should never let the subscriber to complete because it should retain data source
let subscription = concat(returnElements(source, never())).subscribe(AnonymousObserver { event in

View File

@ -10,7 +10,7 @@ import Foundation
import RxSwift
func escapeTerminalString(value: String) -> String {
return value.stringByReplacingOccurrencesOfString("\"", withString: "\\\"", options: NSStringCompareOptions.allZeros, range: nil)
return value.stringByReplacingOccurrencesOfString("\"", withString: "\\\"", options:[], range: nil)
}
func convertURLRequestToCurlCommand(request: NSURLRequest) -> String {
@ -20,13 +20,13 @@ func convertURLRequestToCurlCommand(request: NSURLRequest) -> String {
if request.HTTPMethod == "POST" && request.HTTPBody != nil {
let maybeBody = NSString(data: request.HTTPBody!, encoding: NSUTF8StringEncoding) as? String
if let body = maybeBody {
returnValue += "-d \"\(maybeBody)\""
returnValue += "-d \"\(body)\""
}
}
for (key, value) in request.allHTTPHeaderFields ?? [:] {
let escapedKey = escapeTerminalString((key as? String) ?? "")
let escapedValue = escapeTerminalString((value as? String) ?? "")
let escapedKey = escapeTerminalString((key as String) ?? "")
let escapedValue = escapeTerminalString((value as String) ?? "")
returnValue += "-H \"\(escapedKey): \(escapedValue)\" "
}
@ -37,7 +37,7 @@ func convertURLRequestToCurlCommand(request: NSURLRequest) -> String {
return returnValue
}
func convertResponseToString(data: NSData!, response: NSURLResponse!, error: NSError!, interval: NSTimeInterval) -> String {
func convertResponseToString(data: NSData!, _ response: NSURLResponse!, _ error: NSError!, _ interval: NSTimeInterval) -> String {
let ms = Int(interval * 1000)
if let response = response as? NSHTTPURLResponse {
@ -74,8 +74,8 @@ extension NSURLSession {
if Logging.URLRequests {
let interval = NSDate().timeIntervalSinceDate(d)
println(convertURLRequestToCurlCommand(request))
println(convertResponseToString(data, response, error, interval))
print(convertURLRequestToCurlCommand(request))
print(convertResponseToString(data, response, error, interval))
}
if data == nil || response == nil {
@ -87,10 +87,13 @@ extension NSURLSession {
}
}
task.resume()
if let t = task { t.resume() }
else { sendError(observer, UnknownError) }
return AnonymousDisposable {
task.cancel()
task?.cancel()
}
}
}
@ -102,7 +105,7 @@ extension NSURLSession {
return success(data!)
}
else {
return failure(rxError(.NetworkError, "Server returned failure", [RxCocoaErrorHTTPResponseKey: response]))
return failure(rxError(.NetworkError, message: "Server returned failure", userInfo: [RxCocoaErrorHTTPResponseKey: response]))
}
}
else {
@ -115,15 +118,17 @@ extension NSURLSession {
public func rx_JSON(request: NSURLRequest) -> Observable<AnyObject!> {
return rx_data(request) >- mapOrDie { (data) -> RxResult<AnyObject!> in
var serializationError: NSError?
let result: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: &serializationError)
do {
let result = try NSJSONSerialization.JSONObjectWithData(data, options: [])
return success(result)
}
catch let caught as NSError {
return failure(caught)
}
catch {
return failure(UnknownError)
}
if let result: AnyObject = result {
return success(result)
}
else {
return failure(serializationError!)
}
}
}

View File

@ -25,13 +25,13 @@ public let RxCocoaErrorDomain = "RxCocoaError"
public let RxCocoaErrorHTTPResponseKey = "RxCocoaErrorHTTPResponseKey"
func rxError(errorCode: RxCocoaError, message: String) -> NSError {
func rxError(errorCode: RxCocoaError, _ message: String) -> NSError {
return NSError(domain: RxCocoaErrorDomain, code: errorCode.rawValue, userInfo: [NSLocalizedDescriptionKey: message])
}
#if !RELEASE
public func _rxError(errorCode: RxCocoaError, message: String, userInfo: NSDictionary) -> NSError {
return rxError(errorCode, message, userInfo)
return rxError(errorCode, message: message, userInfo: userInfo)
}
#endif
@ -70,7 +70,7 @@ func rxPossiblyFatalError(error: String) {
#if DEBUG
rxFatalError(error)
#else
println("[RxSwift]: \(error)")
print("[RxSwift]: \(error)")
#endif
}

View File

@ -68,4 +68,4 @@ extension NSTextField {
return delegate.textSubject
}
}
}

View File

@ -10,7 +10,7 @@ import Foundation
import CoreData
import RxSwift
enum CoreDataEntityEvent : Printable {
enum CoreDataEntityEvent : CustomStringConvertible {
typealias SectionInfo = NSFetchedResultsSectionInfo

View File

@ -10,6 +10,7 @@ import Foundation
import CoreData
import RxSwift
/*
class FetchResultControllerSectionObserver: NSObject, NSFetchedResultsControllerDelegate, Disposable {
typealias Observer = ObserverOf<[NSFetchedResultsSectionInfo]>
@ -201,4 +202,4 @@ extension NSManagedObjectContext {
}
}
}
}
}*/

View File

@ -43,7 +43,7 @@ class RxScrollViewDelegateProxy : DelegateProxy
// delegate proxy
override class func createProxyForObject(object: AnyObject) -> Self {
override class func createProxyForObject(object: AnyObject) -> AnyObject {
let scrollView = object as! UIScrollView
return castOrFatalError(scrollView.rx_createDelegateProxy())
@ -64,4 +64,4 @@ class RxScrollViewDelegateProxy : DelegateProxy
sendCompleted(contentOffset)
}
}
}
}

View File

@ -30,7 +30,7 @@ extension UICollectionView {
public func rx_setDataSource(dataSource: UICollectionViewDataSource)
-> Disposable {
let proxy: RxCollectionViewDataSourceProxy = proxyForObject(self)
return installDelegate(proxy, dataSource, false, onProxyForObject: self)
return installDelegate(proxy, delegate: dataSource, retainDelegate: false, onProxyForObject: self)
}
// data source
@ -47,7 +47,7 @@ extension UICollectionView {
public func rx_subscribeWithReactiveDataSource<DataSource: protocol<RxCollectionViewDataSourceType, UICollectionViewDataSource>>
(dataSource: DataSource)
-> Observable<DataSource.Element> -> Disposable {
return setProxyDataSourceForObject(self, dataSource, false) { (_: RxCollectionViewDataSourceProxy, event) -> Void in
return setProxyDataSourceForObject(self, dataSource: dataSource, retainDataSource: false) { (_: RxCollectionViewDataSourceProxy, event) -> Void in
dataSource.collectionView(self, observedEvent: event)
}
}
@ -91,7 +91,7 @@ extension UICollectionView {
public func rx_modelSelected<T>() -> Observable<T> {
return rx_itemSelected >- map { indexPath in
let dataSource: RxCollectionViewReactiveArrayDataSource<T> = castOrFatalError(self.rx_dataSource.forwardToDelegate(), "This method only works in case one of the `rx_subscribeItemsTo` methods was used.")
let dataSource: RxCollectionViewReactiveArrayDataSource<T> = castOrFatalError(self.rx_dataSource.forwardToDelegate(), message: "This method only works in case one of the `rx_subscribeItemsTo` methods was used.")
return dataSource.modelAtIndex(indexPath.item)!
}
@ -100,7 +100,7 @@ extension UICollectionView {
// deprecated
extension UICollectionView {
@availability(*, deprecated=1.7, message="Replaced by `rx_subscribeItemsToWithCellIdentifier`")
@available(*, deprecated=1.7, message="Replaced by `rx_subscribeItemsToWithCellIdentifier`")
public func rx_subscribeItemsWithIdentifierTo<E, Cell where E : AnyObject, Cell : UICollectionViewCell>
(cellIdentifier: String, configureCell: (UICollectionView, NSIndexPath, E, Cell) -> Void)
(source: Observable<[E]>)
@ -112,7 +112,7 @@ extension UICollectionView {
return l(source)
}
@availability(*, deprecated=1.7, message="Replaced by `rx_itemSelected`")
@available(*, deprecated=1.7, message="Replaced by `rx_itemSelected`")
public func rx_itemTap() -> Observable<(UICollectionView, Int)> {
return rx_itemSelected
>- map { i in
@ -120,8 +120,8 @@ extension UICollectionView {
}
}
@availability(*, deprecated=1.7, message="Replaced by `rx_modelSelected`")
@available(*, deprecated=1.7, message="Replaced by `rx_modelSelected`")
public func rx_elementTap<E>() -> Observable<E> {
return rx_modelSelected()
}
}
}

View File

@ -38,6 +38,6 @@ extension UIScrollView {
public func rx_setDelegate(delegate: UIScrollViewDelegate)
-> Disposable {
let proxy: RxScrollViewDelegateProxy = proxyForObject(self)
return installDelegate(proxy, delegate, false, onProxyForObject: self)
return installDelegate(proxy, delegate: delegate, retainDelegate: false, onProxyForObject: self)
}
}
}

View File

@ -28,7 +28,7 @@ extension UITableView {
-> Disposable {
let proxy: RxTableViewDataSourceProxy = proxyForObject(self)
return installDelegate(proxy, dataSource, false, onProxyForObject: self)
return installDelegate(proxy, delegate: dataSource, retainDelegate: false, onProxyForObject: self)
}
// data source
@ -45,7 +45,7 @@ extension UITableView {
public func rx_subscribeWithReactiveDataSource<DataSource: protocol<RxTableViewDataSourceType, UITableViewDataSource>>
(dataSource: DataSource)
-> Observable<DataSource.Element> -> Disposable {
return setProxyDataSourceForObject(self, dataSource, false) { (_: RxTableViewDataSourceProxy, event) -> Void in
return setProxyDataSourceForObject(self, dataSource: dataSource, retainDataSource: false) { (_: RxTableViewDataSourceProxy, event) -> Void in
dataSource.tableView(self, observedEvent: event)
}
}
@ -118,7 +118,7 @@ extension UITableView {
// This method only works in case one of the `rx_subscribeItemsTo` methods was used.
public func rx_modelSelected<T>() -> Observable<T> {
return rx_itemSelected >- map { ip in
let dataSource: RxTableViewReactiveArrayDataSource<T> = castOrFatalError(self.rx_dataSource.forwardToDelegate(), "This method only works in case one of the `rx_subscribeItemsTo` methods was used.")
let dataSource: RxTableViewReactiveArrayDataSource<T> = castOrFatalError(self.rx_dataSource.forwardToDelegate(), message: "This method only works in case one of the `rx_subscribeItemsTo` methods was used.")
return dataSource.modelAtIndex(ip.item)!
}
@ -128,7 +128,7 @@ extension UITableView {
// deprecated
extension UITableView {
@availability(*, deprecated=1.7, message="Replaced by `rx_subscribeWithReactiveDataSource`")
@available(*, deprecated=1.7, message="Replaced by `rx_subscribeWithReactiveDataSource`")
public func rx_subscribeRowsTo<E where E: AnyObject>
(dataSource: UITableViewDataSource)
(source: Observable<[E]>)
@ -136,7 +136,7 @@ extension UITableView {
return rx_setDataSource(dataSource)
}
@availability(*, deprecated=1.7, message="Replaced by `rx_setDataSource`")
@available(*, deprecated=1.7, message="Replaced by `rx_setDataSource`")
public func rx_subscribeRowsTo<E where E : AnyObject>
(cellFactory: (UITableView, NSIndexPath, E) -> UITableViewCell)
(source: Observable<[E]>)
@ -148,7 +148,7 @@ extension UITableView {
return l(source)
}
@availability(*, deprecated=1.7, message="Replaced by `rx_subscribeItemsToWithCellIdentifier`")
@available(*, deprecated=1.7, message="Replaced by `rx_subscribeItemsToWithCellIdentifier`")
public func rx_subscribeRowsToCellWithIdentifier<E, Cell where E : AnyObject, Cell: UITableViewCell>
(cellIdentifier: String, configureCell: (UITableView, NSIndexPath, E, Cell) -> Void)
(source: Observable<[E]>)
@ -159,7 +159,7 @@ extension UITableView {
return l(source)
}
@availability(*, deprecated=1.7, message="Replaced by `rx_itemSelected`")
@available(*, deprecated=1.7, message="Replaced by `rx_itemSelected`")
public func rx_rowTap() -> Observable<(UITableView, Int)> {
return rx_itemSelected
>- map { ip in
@ -167,8 +167,8 @@ extension UITableView {
}
}
@availability(*, deprecated=1.7, message="Replaced by `rx_modelSelected`")
@available(*, deprecated=1.7, message="Replaced by `rx_modelSelected`")
public func rx_elementTap<E>() -> Observable<E> {
return rx_modelSelected()
}
}
}

View File

@ -11,7 +11,7 @@ import RxSwift
import RxCocoa
import CoreData
struct ItemPath : Printable {
struct ItemPath : CustomStringConvertible {
let sectionIndex: Int
let itemIndex: Int
@ -22,7 +22,7 @@ struct ItemPath : Printable {
}
}
public struct Changeset<S: SectionModelType> : Printable {
public struct Changeset<S: SectionModelType> : CustomStringConvertible {
typealias I = S.Item
var finalSections: [S] = []

View File

@ -23,7 +23,7 @@ class RxCollectionViewSectionedAnimatedDataSource<S: SectionModelType> : RxColle
switch observedEvent {
case .Next(let boxedSections):
for c in boxedSections.value {
//println("Animating ==============================\n\(c)\n===============================\n")
//print("Animating ==============================\n\(c)\n===============================\n")
if !set {
setSections(c.finalSections)

View File

@ -19,7 +19,7 @@ class RxTableViewSectionedAnimatedDataSource<S: SectionModelType> : RxTableViewS
switch observedEvent {
case .Next(let boxedSections):
for c in boxedSections.value {
//println("Animating ==============================\n\(c)\n===============================\n")
//print("Animating ==============================\n\(c)\n===============================\n")
setSections(c.finalSections)
tableView.performBatchUpdates(c)
}

View File

@ -8,7 +8,7 @@
import Foundation
enum EditEvent : Printable {
enum EditEvent : CustomStringConvertible {
case Inserted // can't be found in old sections
case Deleted // Was in old, not in new, in it's place is something "not new" :(, otherwise it's Updated
case Moved // same item, but was on different index, and needs explicit move
@ -33,7 +33,7 @@ enum EditEvent : Printable {
}
}
struct SectionAdditionalInfo : Printable {
struct SectionAdditionalInfo : CustomStringConvertible {
var event: EditEvent
var indexAfterDelete: Int?
@ -44,7 +44,7 @@ struct SectionAdditionalInfo : Printable {
}
}
struct ItemAdditionalInfo : Printable {
struct ItemAdditionalInfo : CustomStringConvertible {
var event: EditEvent
var indexAfterDelete: Int?
@ -57,7 +57,7 @@ struct ItemAdditionalInfo : Printable {
func indexSections<S: SectionModelType where S: Hashable, S.Item: Hashable>(sections: [S]) -> [S : Int] {
var indexedSections: [S : Int] = [:]
for (i, section) in enumerate(sections) {
for (i, section) in sections.enumerate() {
precondition(indexedSections[section] == nil, "Section \(section) has already been indexed at \(indexedSections[section]!)")
indexedSections[section] = i
}
@ -75,7 +75,7 @@ func indexSectionItems<S: SectionModelType where S: Hashable, S.Item: Hashable>(
var indexedItems: [S.Item : (Int, Int)] = Dictionary(minimumCapacity: totalItems * 3)
for i in 0 ..< sections.count {
for (j, item) in enumerate(sections[i].items) {
for (j, item) in sections[i].items.enumerate() {
precondition(indexedItems[item] == nil, "Item \(item) has already been indexed at \(indexedItems[item]!)" )
indexedItems[item] = (i, j)
}
@ -247,7 +247,7 @@ func differentiate<S: SectionModelType where S: Hashable, S.Item: Hashable>(
// mark deleted sections {
// 1rst stage
var sectionIndexAfterDelete = 0
for (i, initialSection) in enumerate(initialSections) {
for (i, initialSection) in initialSections.enumerate() {
if finalSectionIndexes[initialSection] == nil {
initialSectionInfos[i].event = .Deleted
deletes.deletedSections.append(i)
@ -280,7 +280,7 @@ func differentiate<S: SectionModelType where S: Hashable, S.Item: Hashable>(
// inserted and moved sections {
// this should fix all sections and move them into correct places
// 2nd stage
for (i, finalSection) in enumerate(finalSections) {
for (i, finalSection) in finalSections.enumerate() {
untouchedOldIndex = findNextUntouchedOldIndex(untouchedOldIndex)
// oh, it did exist
@ -304,7 +304,7 @@ func differentiate<S: SectionModelType where S: Hashable, S.Item: Hashable>(
// mark deleted items {
// 1rst stage again (I know, I know ...)
for (i, initialSection) in enumerate(initialSections) {
for (i, initialSection) in initialSections.enumerate() {
let event = initialSectionInfos[i].event
// Deleted section will take care of deleting child items.
@ -315,7 +315,7 @@ func differentiate<S: SectionModelType where S: Hashable, S.Item: Hashable>(
}
var indexAfterDelete = 0
for (j, initialItem) in enumerate(initialSection.items) {
for (j, initialItem) in initialSection.items.enumerate() {
if let finalItemIndex = finalItemIndexes[initialItem] {
let targetSectionEvent = finalSectionInfos[finalItemIndex.0].event
// In case there is move of item from existing section into new section
@ -341,7 +341,7 @@ func differentiate<S: SectionModelType where S: Hashable, S.Item: Hashable>(
// mark new and moved items {
// 3rd stage
for (i, finalSection) in enumerate(finalSections) {
for (i, finalSection) in finalSections.enumerate() {
let finalSection = finalSections[i]
var originalSection: Int? = initialSectionIndexes[finalSection]
@ -367,7 +367,7 @@ func differentiate<S: SectionModelType where S: Hashable, S.Item: Hashable>(
continue
}
for (j, finalItem) in enumerate(finalSection.items) {
for (j, finalItem) in finalSection.items.enumerate() {
let currentItemEvent = finalItemInfos[i][j].event
precondition(currentItemEvent == .Untouched)
@ -399,7 +399,7 @@ func differentiate<S: SectionModelType where S: Hashable, S.Item: Hashable>(
? EditEvent.MovedAutomatically : EditEvent.Moved
// println("\(finalItem) \(eventType) \(originalIndex), \(originalSection) \(untouchedOldIndex)")
// print("\(finalItem) \(eventType) \(originalIndex), \(originalSection) \(untouchedOldIndex)")
initialItemInfos[originalIndex.0][originalIndex.1].event = eventType
finalItemInfos[i][j].event = eventType
@ -429,13 +429,13 @@ func differentiate<S: SectionModelType where S: Hashable, S.Item: Hashable>(
if deletes.deletedItems.count > 0 || deletes.deletedSections.count > 0 {
deletes.finalSections = []
for (i, s) in enumerate(initialSections) {
for (i, s) in initialSections.enumerate() {
if initialSectionInfos[i].event == .Deleted {
continue
}
var items: [I] = []
for (j, item) in enumerate(s.items) {
for (j, item) in s.items.enumerate() {
if initialItemInfos[i][j].event != .Deleted {
items.append(item)
}
@ -448,7 +448,7 @@ func differentiate<S: SectionModelType where S: Hashable, S.Item: Hashable>(
if newAndMovedSections.insertedSections.count > 0 || newAndMovedSections.movedSections.count > 0 || newAndMovedSections.updatedSections.count != 0 {
// sections should be in place, but items should be original without deleted ones
newAndMovedSections.finalSections = []
for (i, s) in enumerate(finalSections) {
for (i, s) in finalSections.enumerate() {
let event = finalSectionInfos[i].event
if event == .Inserted {
@ -460,7 +460,7 @@ func differentiate<S: SectionModelType where S: Hashable, S.Item: Hashable>(
let originalSection = initialSections[originalSectionIndex]
var items: [I] = []
for (j, item) in enumerate(originalSection.items) {
for (j, item) in originalSection.items.enumerate() {
if initialItemInfos[originalSectionIndex][j].event != .Deleted {
items.append(item)
}

View File

@ -8,7 +8,7 @@
import Foundation
public struct SectionModel<Section, ItemType> : SectionModelType, Printable {
public struct SectionModel<Section, ItemType> : SectionModelType, CustomStringConvertible {
typealias Item = ItemType
public var model: Section
@ -31,7 +31,7 @@ public struct SectionModel<Section, ItemType> : SectionModelType, Printable {
}
}
public struct HashableSectionModel<Section: Hashable, ItemType: Hashable> : Hashable, SectionModelType, Printable {
public struct HashableSectionModel<Section: Hashable, ItemType: Hashable> : Hashable, SectionModelType, CustomStringConvertible {
typealias Item = ItemType
public var model: Section

View File

@ -52,7 +52,7 @@ extension UITableView : SectionedViewType {
func performBatchUpdates<S: SectionModelType>(changes: Changeset<S>) {
self.beginUpdates()
_performBatchUpdates(self, changes)
_performBatchUpdates(self, changes: changes)
self.endUpdates()
}
}
@ -92,7 +92,7 @@ extension UICollectionView : SectionedViewType {
func performBatchUpdates<S: SectionModelType>(changes: Changeset<S>) {
self.performBatchUpdates({ () -> Void in
_performBatchUpdates(self, changes)
_performBatchUpdates(self, changes: changes)
}, completion: { (completed: Bool) -> Void in
})
}
@ -125,8 +125,6 @@ func setFor<E, K>(items: [E], transform: E -> K) -> [K : K] {
func _performBatchUpdates<V: SectionedViewType, S: SectionModelType>(view: V, changes: Changeset<S>) {
typealias I = S.Item
let cv: UICollectionView
let rowAnimation = UITableViewRowAnimation.Automatic
view.deleteSections(changes.deletedSections, animationStyle: rowAnimation)

View File

@ -20,9 +20,6 @@
C83367251AD029AE00C668A7 /* ImageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = C83367121AD029AE00C668A7 /* ImageService.swift */; };
C83367311AD029AE00C668A7 /* Wireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = C83367211AD029AE00C668A7 /* Wireframe.swift */; };
C859B9A41B45C5D900D012D7 /* PartialUpdatesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C859B9A31B45C5D900D012D7 /* PartialUpdatesViewController.swift */; };
C859B9A61B45C80700D012D7 /* RxCollectionViewSectionedReloadDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = C859B9A51B45C80700D012D7 /* RxCollectionViewSectionedReloadDataSource.swift */; };
C859B9A81B45C83700D012D7 /* RxCollectionViewSectionedDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = C859B9A71B45C83700D012D7 /* RxCollectionViewSectionedDataSource.swift */; };
C859B9AA1B45CB0900D012D7 /* RxCollectionViewSectionedAnimatedDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = C859B9A91B45CB0900D012D7 /* RxCollectionViewSectionedAnimatedDataSource.swift */; };
C859B9AC1B45CF9100D012D7 /* NumberCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C859B9AB1B45CF9100D012D7 /* NumberCell.swift */; };
C859B9AE1B45CFAB00D012D7 /* NumberSectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C859B9AD1B45CFAB00D012D7 /* NumberSectionView.swift */; };
C86E2F3E1AE5A0CA00C31024 /* SearchResultViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C86E2F321AE5A0CA00C31024 /* SearchResultViewModel.swift */; };
@ -45,9 +42,6 @@
C88BB8CF1B07E6C90064D411 /* RxCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C8F57F431AD02DBE006B8702 /* RxCocoa.framework */; };
C88BB8D71B07E6C90064D411 /* RxSwift.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C8A56BCA1AD744E600B4673B /* RxSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
C88BB8D81B07E6C90064D411 /* RxCocoa.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C8F57F431AD02DBE006B8702 /* RxCocoa.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
C88C786D1B3EB0A00061C5AB /* RxTableViewSectionedAnimatedDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = C88C78631B3EB0A00061C5AB /* RxTableViewSectionedAnimatedDataSource.swift */; };
C88C786E1B3EB0A00061C5AB /* RxTableViewSectionedDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = C88C78641B3EB0A00061C5AB /* RxTableViewSectionedDataSource.swift */; };
C88C786F1B3EB0A00061C5AB /* RxTableViewSectionedReloadDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = C88C78651B3EB0A00061C5AB /* RxTableViewSectionedReloadDataSource.swift */; };
C88C78721B3EB0A00061C5AB /* SectionedViewType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C88C78691B3EB0A00061C5AB /* SectionedViewType.swift */; };
C88C78731B3EB0A00061C5AB /* SectionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C88C786A1B3EB0A00061C5AB /* SectionModel.swift */; };
C88C788F1B3F14FD0061C5AB /* Changeset.swift in Sources */ = {isa = PBXBuildFile; fileRef = C88C788E1B3F14FD0061C5AB /* Changeset.swift */; };
@ -537,7 +531,6 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C88C786D1B3EB0A00061C5AB /* RxTableViewSectionedAnimatedDataSource.swift in Sources */,
0706E19F1B17703E00BA2D3A /* RandomUserAPI.swift in Sources */,
C86E2F3E1AE5A0CA00C31024 /* SearchResultViewModel.swift in Sources */,
C83367241AD029AE00C668A7 /* HtmlParsing.swift in Sources */,
@ -545,7 +538,6 @@
0706E19B1B17361100BA2D3A /* UIImageView+Extensions.swift in Sources */,
C859B9AE1B45CFAB00D012D7 /* NumberSectionView.swift in Sources */,
C8DF92E51B0B32DA009BCF9A /* RootViewController.swift in Sources */,
C859B9A81B45C83700D012D7 /* RxCollectionViewSectionedDataSource.swift in Sources */,
C88C788F1B3F14FD0061C5AB /* Changeset.swift in Sources */,
C8C46DA81B47F7110020D71E /* CollectionViewImageCell.swift in Sources */,
C8C46DAC1B47F7110020D71E /* WikipediaSearchViewController.swift in Sources */,
@ -555,7 +547,6 @@
0706E1961B14AF5100BA2D3A /* DetailViewController.swift in Sources */,
C88C78991B4012A90061C5AB /* SectionModelType.swift in Sources */,
C83367251AD029AE00C668A7 /* ImageService.swift in Sources */,
C859B9A61B45C80700D012D7 /* RxCollectionViewSectionedReloadDataSource.swift in Sources */,
C86E2F471AE5A0CA00C31024 /* WikipediaSearchResult.swift in Sources */,
C890A65A1AEBD28A00AFF7E6 /* GitHubAPI.swift in Sources */,
C8A2A2C81B4049E300F11F09 /* PseudoRandomGenerator.swift in Sources */,
@ -575,7 +566,6 @@
07E3C2331B03605B0010338D /* Dependencies.swift in Sources */,
C86E2F451AE5A0CA00C31024 /* WikipediaAPI.swift in Sources */,
C8DF92CD1B0B2F84009BCF9A /* AppDelegate.swift in Sources */,
C88C786E1B3EB0A00061C5AB /* RxTableViewSectionedDataSource.swift in Sources */,
C86E2F461AE5A0CA00C31024 /* WikipediaPage.swift in Sources */,
C8A2A2CB1B404A1200F11F09 /* Randomizer.swift in Sources */,
07E300091B149A2A00F00100 /* User.swift in Sources */,

View File

@ -53,7 +53,7 @@ class GitHubAPI {
}
}
>- observeSingleOn(self.dataScheduler)
>- catch { result in
>- onError { result in
return just(false)
}
}

View File

@ -29,7 +29,7 @@ class ValidationService {
let minPasswordCount = 5
func validateUsername(username: String) -> Observable<ValidationResult> {
if count(username) == 0 {
if username.characters.count == 0 {
return just((false, nil))
}
@ -53,7 +53,7 @@ class ValidationService {
}
func validatePassword(password: String) -> ValidationResult {
let numberOfCharacters = count(password)
let numberOfCharacters = password.characters.count
if numberOfCharacters == 0 {
return (false, nil)
}
@ -66,7 +66,7 @@ class ValidationService {
}
func validateRepeatedPassword(password: String, repeatedPassword: String) -> ValidationResult {
if count(repeatedPassword) == 0 {
if repeatedPassword.characters.count == 0 {
return (false, nil)
}

View File

@ -27,8 +27,8 @@ class IntroductionExampleViewController : ViewController {
super.viewDidLoad()
// c = a + b
let sum = combineLatest(a.rx_text, b.rx_text) { (a, b) in
return (a.toInt() ?? 0, b.toInt() ?? 0)
let sum = combineLatest(a.rx_text, b.rx_text) { (a, b) -> Int in
return (Int(a) ?? 0, Int(b) ?? 0)
}
// bind result to UI
@ -72,7 +72,7 @@ class IntroductionExampleViewController : ViewController {
disposeButton.rx_tap
>- subscribeNext { [unowned self] _ in
println("Unbound everything")
print("Unbound everything")
self.disposeBag = DisposeBag()
}
>- disposeBag.addDisposable

View File

@ -17,6 +17,7 @@ let runAutomatically = false
let useAnimatedUpdateForCollectionView = false
class PartialUpdatesViewController : ViewController {
/*
@IBOutlet weak var reloadTableViewOutlet: UITableView!
@IBOutlet weak var partialUpdatesTableViewOutlet: UITableView!
@IBOutlet weak var partialUpdatesCollectionViewOutlet: UICollectionView!
@ -50,7 +51,7 @@ class PartialUpdatesViewController : ViewController {
func skinTableViewDataSource(dataSource: RxTableViewSectionedDataSource<NumberSection>) {
dataSource.cellFactory = { (tv, ip, i) in
let cell = tv.dequeueReusableCellWithIdentifier("Cell") as? UITableViewCell
let cell = tv.dequeueReusableCellWithIdentifier("Cell")!
?? UITableViewCell(style:.Default, reuseIdentifier: "Cell")
cell.textLabel!.text = "\(i)"
@ -120,7 +121,7 @@ class PartialUpdatesViewController : ViewController {
// reactive data sources
let updates = zip(self.sections, newSections) { (old, new) in
return differentiate(old, new)
return differentiate(old, finalSections: new)
}
>- startWith(initialState)
@ -163,13 +164,13 @@ class PartialUpdatesViewController : ViewController {
partialUpdatesCollectionViewOutlet.rx_itemSelected
>- subscribeNext { [unowned self] i in
println("Let me guess, it's .... It's \(self.generator.sections[i.section].items[i.item]), isn't it? Yeah, I've got it.")
print("Let me guess, it's .... It's \(self.generator.sections[i.section].items[i.item]), isn't it? Yeah, I've got it.")
}
>- disposeBag.addDisposable
merge(from([partialUpdatesTableViewOutlet.rx_itemSelected, reloadTableViewOutlet.rx_itemSelected]))
>- subscribeNext { [unowned self] i in
println("I have a feeling it's .... \(self.generator.sections[i.section].items[i.item])?")
print("I have a feeling it's .... \(self.generator.sections[i.section].items[i.item])?")
}
>- disposeBag.addDisposable
}
@ -187,8 +188,8 @@ class PartialUpdatesViewController : ViewController {
values = PartialUpdatesViewController.firstChange!
}
//println(values)
//print(values)
sections.next(values)
}
}*/
}

View File

@ -39,8 +39,8 @@ class RandomUserAPI {
let pictures = user?["picture"] as? [String: String]
if let firstName = name?["first"], let lastName = name?["last"], let imageURL = pictures?["medium"] {
let returnUser = User(firstName: firstName.uppercaseFirstCharacter(),
lastName: lastName.uppercaseFirstCharacter(),
let returnUser = User(firstName: firstName.capitalizedString,
lastName: lastName.capitalizedString,
imageURL: imageURL)
return success(returnUser)
}

View File

@ -8,10 +8,4 @@
extension String {
func uppercaseFirstCharacter() -> String {
var result = Array(self)
if !isEmpty { result[0] = Character(String(result.first!).uppercaseString) }
return String(result)
}
}

View File

@ -12,6 +12,7 @@ import RxCocoa
class TableViewController: ViewController, UITableViewDelegate {
/*
@IBOutlet weak var tableView: UITableView!
var disposeBag = DisposeBag()
@ -46,7 +47,7 @@ class TableViewController: ViewController, UITableViewDelegate {
>- disposeBag.addDisposable
dataSource.cellFactory = { (tv, ip, user: User) in
let cell = tv.dequeueReusableCellWithIdentifier("Cell") as! UITableViewCell
let cell = tv.dequeueReusableCellWithIdentifier("Cell")!
cell.textLabel?.text = user.firstName + " " + user.lastName
return cell
}
@ -86,7 +87,7 @@ class TableViewController: ViewController, UITableViewDelegate {
// Rx content offset
tableView.rx_contentOffset
>- subscribeNext { co in
println("Content offset from Rx observer \(co)")
print("Content offset from Rx observer \(co)")
}
RandomUserAPI.sharedAPI.getExampleUserResultSet()
@ -123,7 +124,7 @@ class TableViewController: ViewController, UITableViewDelegate {
}
func scrollViewDidScroll(scrollView: UIScrollView) {
println("Content offset from delegate \(scrollView.contentOffset)")
print("Content offset from delegate \(scrollView.contentOffset)")
}
// MARK: Navigation
@ -204,5 +205,5 @@ class TableViewController: ViewController, UITableViewDelegate {
fatalError("Section out of range")
}
}
*/
}

View File

@ -1,7 +1,7 @@
import Foundation
struct User: Equatable, Printable {
struct User: Equatable, CustomStringConvertible {
var firstName: String
var lastName: String

View File

@ -27,14 +27,14 @@ class SearchResultViewModel {
let URLs = configureImageURLs()
self.imageURLs = URLs >- catch([])
self.title = configureTitle(URLs) >- catch("Error during fetching")
self.imageURLs = URLs >- onError ([])
self.title = configureTitle(URLs) >- onError("Error during fetching")
}
// private methods
func configureTitle(imageURLs: Observable<[NSURL]>) -> Observable<String> {
var searchResult = self.searchResult
let searchResult = self.searchResult
let loadingValue: [NSURL]? = nil
@ -56,7 +56,11 @@ class SearchResultViewModel {
return API.articleContent(searchResult)
>- observeSingleOn($.backgroundWorkScheduler)
>- map { page in
parseImageURLsfromHTMLSuitableForDisplay(page.text)
do {
return try parseImageURLsfromHTMLSuitableForDisplay(page.text)
} catch {
return []
}
}
>- observeSingleOn($.mainScheduler)
>- variable

View File

@ -32,7 +32,7 @@ class SearchViewModel: Disposable {
>- map { query in
API.getSearchResults(query)
>- startWith([]) // clears results on new search term
>- catch([])
>- onError ([])
}
>- switchLatest
>- map { results in

View File

@ -42,7 +42,7 @@ public class WikipediaSearchCell: UITableViewCell {
cell.image = self.imageService.imageFromURL(URL)
>- map { $0 as UIImage? }
>- catch(nil)
>- onError(nil)
>- startWith(loadingPlaceholder)
}
>- disposeBag.addDisposable

View File

@ -62,4 +62,4 @@ class WikipediaSearchViewController: ViewController {
self.viewModel = viewModel
// }
}
}
}

View File

@ -9,7 +9,7 @@
import Foundation
import RxSwift
struct WikipediaSearchResult: Printable {
struct WikipediaSearchResult: CustomStringConvertible {
let title: String
let description: String
let URL: NSURL
@ -34,7 +34,8 @@ struct WikipediaSearchResult: Printable {
let titleDescriptionAndUrl: [((AnyObject, AnyObject), AnyObject)] = Array(Zip2(titleAndDescription, rootArrayTyped[2]))
let searchResults: [RxResult<WikipediaSearchResult>] = titleDescriptionAndUrl.map ( { result -> RxResult<WikipediaSearchResult> in
let ((title: AnyObject, description: AnyObject), url: AnyObject) = result
let (first, url) = result
let (title, description) = first
let titleString = title as? String,
descriptionString = description as? String,

View File

@ -8,10 +8,10 @@
import Foundation
func parseImageURLsfromHTML(html: NSString) -> [NSURL] {
let regularExpression = NSRegularExpression(pattern: "<img[^>]*src=\"([^\"]+)\"[^>]*>", options: NSRegularExpressionOptions.allZeros, error: nil)!
func parseImageURLsfromHTML(html: NSString) throws -> [NSURL] {
let regularExpression = try NSRegularExpression(pattern: "<img[^>]*src=\"([^\"]+)\"[^>]*>", options: [])
let matches = regularExpression.matchesInString(html as! String, options: NSMatchingOptions.allZeros, range: NSMakeRange(0, html.length)) as! [NSTextCheckingResult]
let matches = regularExpression.matchesInString(html as! String, options: [], range: NSMakeRange(0, html.length)) as! [NSTextCheckingResult]
return matches.map { match -> NSURL? in
if match.numberOfRanges != 2 {
@ -29,13 +29,8 @@ func parseImageURLsfromHTML(html: NSString) -> [NSURL] {
}.filter { $0 != nil }.map { $0! }
}
func parseImageURLsfromHTMLSuitableForDisplay(html: NSString) -> [NSURL] {
return parseImageURLsfromHTML(html).filter {
if let absoluteString = $0.absoluteString {
return absoluteString.rangeOfString(".svg.") == nil
}
else {
return false
}
func parseImageURLsfromHTMLSuitableForDisplay(html: NSString) throws -> [NSURL] {
return try parseImageURLsfromHTML(html).filter {
return $0.absoluteString.rangeOfString(".svg.") == nil
}
}

View File

@ -55,7 +55,7 @@ class DefaultImageService: ImageService {
}
func imageFromURL(URL: NSURL) -> Observable<Image> {
return defer {
return deferred {
let maybeImage = self.imageDataCache.objectForKey(URL) as? Image
let decodedImage: Observable<Image>

View File

@ -37,7 +37,7 @@ class Randomizer {
}
func countTotalItemsInSections(sections: [NumberSection]) -> Int {
return reduce(sections, 0) { p, s in
return sections.reduce(0) { p, s in
return p + s.items.count
}
}

View File

@ -24,13 +24,13 @@ class ViewController: OSViewController {
override func viewDidLoad() {
#if TRACE_RESOURCES
println("Number of start resources = \(resourceCount)")
print("Number of start resources = \(resourceCount)")
#endif
}
deinit {
#if TRACE_RESOURCES
println("View controller disposed with \(resourceCount) resources")
print("View controller disposed with \(resourceCount) resources")
var numberOfResourcesThatShouldRemain = startResourceCount
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC)))

View File

@ -17,10 +17,17 @@ public enum RxErrorCode : Int {
case Disposed = 3
}
// This defines error type for entire project.
// It's not practical to have different error handling types for different areas of the app.
// This is good enough solution for now unless proven otherwise
public typealias ErrorType = NSError
// just temporary
public func errorEquals(lhs: ErrorType, _ rhs: ErrorType) -> Bool {
if let error1 = lhs as? NSError {
if let error2 = rhs as? NSError {
return error1 === error2
}
}
return false
}
public let UnknownError = NSError(domain: RxErrorDomain, code: RxErrorCode.Unknown.rawValue, userInfo: nil)
public let CastError = NSError(domain: RxErrorDomain, code: RxErrorCode.Cast.rawValue, userInfo: nil)

View File

@ -53,7 +53,8 @@ public func eventType<T>(event: Event<T>) -> String {
public func == <T: Equatable>(lhs: Event<T>, rhs: Event<T>) -> Bool {
switch (lhs, rhs) {
case (.Completed, .Completed): return true
case (.Error(let e1), .Error(let e2)): return e1 == e2
// really stupid fix for now
case (.Error(let e1), .Error(let e2)): return "\(e1)" == "\(e2)"
case (.Next(let v1), .Next(let v2)): return v1.value == v2.value
default: return false
}

View File

@ -144,7 +144,7 @@ public func take<E, S: Scheduler>
// skip
public func skip<E, S: Scheduler>
(duration: S.TimeInterval, scheduler: S)
(duration: S.TimeInterval, _ scheduler: S)
-> Observable<E> -> Observable<E> {
return { source in
return SkipTime(source: source, duration: duration, scheduler: scheduler)

View File

@ -51,7 +51,7 @@ public func dispatch<Element, S: SequenceType where S.Generator.Element == Obser
// where S.Generator.Element == ObserverOf<Element>
// Crashes the compiler
//public func dispatchNext<Element, S: SequenceType where S.Generator.Element == ObserverOf<Element>>(element: Element, observers: S?) {
//public func dispatchNext<Element, S: SequenceType where S.Generator.Element == ObserverOf<Element>>(element: Element, _ observers: S?) {
// if let observers = observers {
// let event = Event.Next(RxBox(element))
// for o in observers {
@ -61,7 +61,7 @@ public func dispatch<Element, S: SequenceType where S.Generator.Element == Obser
//}
public func dispatchNext<Element, S: SequenceType where S.Generator.Element == ObserverOf<Element>>(element: Element, observers: S) {
public func dispatchNext<Element, S: SequenceType where S.Generator.Element == ObserverOf<Element>>(element: Element, _ observers: S) {
let event = Event.Next(RxBox(element))
for o in observers {
o.on(event)

View File

@ -8,6 +8,10 @@
import Foundation
func justUseIt<T>(_: T) {
}
#if TRACE_RESOURCES
// counts resources
// used to detect resource leaks during unit tests

View File

@ -53,7 +53,7 @@ func getScheduledDisposable(disposable: RxResult<Disposable>) -> Disposable {
}
func errorDuringScheduledAction(error: ErrorType) -> RxResult<Void> {
let exception = NSException(name: "ScheduledActionError", reason: "Error happened during scheduled action execution", userInfo: ["error": error])
let exception = NSException(name: "ScheduledActionError", reason: "Error happened during scheduled action execution", userInfo: ["error": error as! AnyObject])
exception.raise()
return SuccessResult

View File

@ -8,7 +8,7 @@
import Foundation
@availability(*, deprecated=1.7, message="Replaced by `SerialDispatchQueueScheduler`")
@available(*, deprecated=1.7, message="Replaced by `SerialDispatchQueueScheduler`")
public typealias DispatchQueueScheduler = SerialDispatchQueueScheduler
// This is a scheduler that wraps dispatch queue.

View File

@ -34,7 +34,7 @@ class Subscription<Element> : Disposable {
}
}
@availability(*, deprecated=1.7, message="Replaced by PublishSubject")
@available(*, deprecated=1.7, message="Replaced by PublishSubject")
public class Subject<Element> : PublishSubject<Element> {
public override init() {

View File

@ -133,7 +133,7 @@ extension KVOObservableTests {
func test_New_And_Initial() {
let testClass = TestClass()
let os: Observable<String?> = testClass.rx_observe("pr", options: .Initial | .New)
let os: Observable<String?> = testClass.rx_observe("pr", options: .Initial)
var latest: String?

View File

@ -14,9 +14,9 @@ import RxCocoa
class RxCocoaTest : RxTest {
#if !RELEASE
func testRxError() {
let result = _rxError(RxCocoaError.NetworkError, "my bad", ["a": 1])
let result = _rxError(RxCocoaError.NetworkError, message: "my bad", userInfo: ["a": 1])
let dUserInfo = NSDictionary(dictionary: result.userInfo!)
let dUserInfo = NSDictionary(dictionary: result.userInfo)
XCTAssertTrue(dUserInfo.isEqualToDictionary([NSLocalizedDescriptionKey: "my bad", "a" : 1]))
}
#endif

View File

@ -50,7 +50,7 @@ class UIRxTests : RxTest {
let resultLabel = UILabelMock()
let disposable = primeTextField.rx_text()
>- map { WolframAlphaIsPrime($0.toInt() ?? 0) }
>- map { WolframAlphaIsPrime(Int($0) ?? 0) }
>- concat
>- map { "number \($0.n) is prime? \($0.isPrime)" }
>- resultLabel.rx_subscribeTextTo

View File

@ -20,7 +20,7 @@ public func == <E>(lhs: RxResult<E>, rhs: RxResult<E>) -> Bool {
var val2 = boxed2.value
return memcmp(&val1, &val2, sizeof(E)) == 0
case (.Failure(let error1), .Failure(let error2)):
return error1 === error2
return errorEquals(error1, error2)
default:
return false
}

View File

@ -158,7 +158,7 @@ extension ObservableBindingTest {
case .Next:
XCTAssertTrue(false)
case .Error(let error):
XCTAssertEqual(error, testError)
XCTAssertErrorEqual(error, testError)
case .Completed:
XCTAssertTrue(false)
}
@ -168,7 +168,7 @@ extension ObservableBindingTest {
case .Next:
XCTAssertTrue(false)
case .Error(let error):
XCTAssertEqual(error, testError)
XCTAssertErrorEqual(error, testError)
case .Completed:
XCTAssertTrue(false)
}

View File

@ -540,7 +540,7 @@ class ObservableConcurrentSchedulerConcurrencyTest: ObservableConcurrencyTestBas
}
let disposable2 = scheduler.schedule(()) { _ in
//println("variable \(variable)")
//print("variable \(variable)")
self.performLocked {
events.append("Started")
}

View File

@ -123,7 +123,7 @@ class VariableTest : RxTest {
var latestValueOfC : Int? = nil
// let _ = doesn't retain.
_/*: Disposable*/ = c >- subscribeNext { c in
//println("Next value of c = \(c)")
//print("Next value of c = \(c)")
latestValueOfC = c
} >- scopedDispose

View File

@ -24,6 +24,10 @@ import RxSwift
typealias Time = Int
func XCTAssertErrorEqual(lhs: ErrorType, _ rhs: ErrorType) {
XCTAssertTrue(errorEquals(lhs, rhs))
}
let testError = NSError(domain: "dummyError", code: -232, userInfo: nil)
let testError1 = NSError(domain: "dummyError1", code: -233, userInfo: nil)
let testError2 = NSError(domain: "dummyError2", code: -234, userInfo: nil)