Documentation and interface cleanup.
This commit is contained in:
parent
6139b16ca3
commit
c4ea7b4bb2
21
CHANGELOG.md
21
CHANGELOG.md
|
|
@ -3,7 +3,24 @@ All notable changes to this project will be documented in this file.
|
|||
|
||||
---
|
||||
|
||||
## [2.0](https://github.com/ReactiveX/RxSwift/pull/50) (WIP)
|
||||
## [2.0.0-alpha.2](https://github.com/ReactiveX/RxSwift/pull/50) (WIP)
|
||||
|
||||
#### Updated
|
||||
|
||||
* Renames `ScopedDispose` to `ScopedDisposable`
|
||||
* Deprecates `observeSingleOn` in favor of `observeOn`
|
||||
* Adds inline documentation
|
||||
* Renames `from` to `asObservable` extension method on `SequenceType`
|
||||
* Renames `catchErrorResumeNext` in favor of `catchErrorJustReturn`
|
||||
* Deprecates `catchErrorToResult`, the preferred way is to use Swift `do/try/catch` mechanism.
|
||||
* Deprecates `RxResult`, the preferred way is to use Swift `do/try/catch` mechanism.
|
||||
* Deprecates `sendNext` on `Variable` in favor of just using `value` setter.
|
||||
|
||||
## [2.0.0-alpha.1](https://github.com/ReactiveX/RxSwift/pull/50) (WIP)
|
||||
|
||||
#### Fixed
|
||||
|
||||
* Problem in RxExample with missing `observeOn` for images.
|
||||
|
||||
#### Updated
|
||||
|
||||
|
|
@ -16,7 +33,7 @@ All notable changes to this project will be documented in this file.
|
|||
* Deprecates `returnElement` in favor of `just`
|
||||
* Deprecates `aggregate` in favor of `reduce`
|
||||
* Deprecates `variable` in favor of `shareReplay(1)` (to be consistent with RxJS version)
|
||||
* Method `next` on `Variable` is now `sendNext`
|
||||
* Method `next` on `Variable` in favor of `sendNext`
|
||||
|
||||
|
||||
#### Fixed
|
||||
|
|
|
|||
|
|
@ -90,17 +90,18 @@ protocol ObserverType {
|
|||
}
|
||||
```
|
||||
|
||||
**When sequence sends `Complete` or `Error` event all internal resources that compute sequence elements will be freed.**
|
||||
|
||||
**To cancel production of sequence elements and free resources immediatelly, call `dispose` on returned subscription.**
|
||||
|
||||
If a sequence terminates in finite time, not calling `dispose` or not using `addDisposableTo(disposeBag)` won't cause any permanent resource leaks, but those resources will be used until sequence completes in some way (finishes producing elements or error happens).
|
||||
|
||||
If a sequence doesn't terminate in some way, resources will be allocated permanently unless `dispose` is being called manually, automatically inside of a `disposeBag`, `scopedDispose`, `takeUntil` or some other way.
|
||||
|
||||
**Using dispose bags, scoped dispose or `takeUntil` operator are all robust ways of making sure resources are cleaned up and we recommend using them in production even though sequence will terminate in finite time.**
|
||||
|
||||
In case you are curious why `ErrorType` isn't generic, you can find explanation [here](DesignRationale.md#why-error-type-isnt-generic).
|
||||
|
||||
So the only thing left on the table is `Disposable`.
|
||||
|
||||
```swift
|
||||
protocol Disposable
|
||||
{
|
||||
func dispose()
|
||||
}
|
||||
```
|
||||
|
||||
## Disposing
|
||||
|
||||
There is one additional way an observed sequence can terminate. When you are done with a sequence and want to release all of the resources that were allocated to compute upcoming elements, calling dispose on a subscription will clean this up for you.
|
||||
|
|
@ -130,7 +131,7 @@ This will print:
|
|||
5
|
||||
```
|
||||
|
||||
One thing to note here is that you usually don't want to manually call `dispose` and this is only educational example. Calling dispose manually is usually bad code smell, and there are better ways to dispose subscriptions. You can either use `DisposeBag`, `ScopedDispose`, `takeUntil` operator or some other mechanism.
|
||||
One thing to note here is that you usually don't want to manually call `dispose` and this is only educational example. Calling dispose manually is usually bad code smell, and there are better ways to dispose subscriptions. You can either use `DisposeBag`, `ScopedDisposable`, `takeUntil` operator or some other mechanism.
|
||||
|
||||
So can this code print something after `dispose` call executed? The answer is, it depends.
|
||||
|
||||
|
|
@ -183,6 +184,48 @@ subscription.dispose() // executing on same `serialScheduler`
|
|||
|
||||
**After `dispose` call returns, nothing will be printed. That is a guarantee.**
|
||||
|
||||
### Dispose Bags
|
||||
|
||||
Dispose bags are used to return ARC like behavior to RX.
|
||||
|
||||
When `DisposeBag` is deallocated, it will call `dispose` on each of the added disposables.
|
||||
|
||||
It doesn't have a `dispose` method and it doesn't allow calling explicit dispose on purpose. If immediate cleanup is needed just create a new bag.
|
||||
|
||||
```swift
|
||||
self.disposeBag = DisposeBag()
|
||||
```
|
||||
|
||||
That should clear references to old one and cause disposal of resources.
|
||||
|
||||
If that explicit manual disposal is still wanted, use `CompositeDisposable`. **It has the wanted behavior but once that `dispose` method is called, it will immediately dispose any newly added disposable.**
|
||||
|
||||
### Scoped Dispose
|
||||
|
||||
In case disposal is wanted immediately after leaving scope of execution, there is `scopedDispose()`.
|
||||
|
||||
```swift
|
||||
let autoDispose = sequence
|
||||
.subscribe {
|
||||
print($0)
|
||||
}
|
||||
.scopedDispose()
|
||||
```
|
||||
|
||||
This will dispose the subscription when execution leaves current scope.
|
||||
|
||||
### Take until
|
||||
|
||||
Additional way to automatically dispose subscription on dealloc is to use `takeUntil` operator.
|
||||
|
||||
```swift
|
||||
sequence
|
||||
.takeUntil(self.rx_deallocated)
|
||||
.subscribe {
|
||||
print($0)
|
||||
}
|
||||
```
|
||||
|
||||
## Implicit `Observable` guarantees
|
||||
|
||||
There is also a couple of additional guarantees that all sequence producers (`Observable`s) must honor.
|
||||
|
|
@ -363,7 +406,7 @@ func myInterval(interval: NSTimeInterval) -> Observable<Int> {
|
|||
if cancel.disposed {
|
||||
return
|
||||
}
|
||||
sendNext(observer, next++)
|
||||
observer.on(.Next(next++))
|
||||
})
|
||||
dispatch_resume(timer)
|
||||
|
||||
|
|
@ -912,7 +955,7 @@ The reason why you should use a small delay is because sometimes it takes a smal
|
|||
|
||||
`Variable`s represent some observable state. `Variable` without containing value can't exist because initializer requires initial value.
|
||||
|
||||
Variable wraps a [`Subject`](http://reactivex.io/documentation/subject.html). More specifically it is a `BehaviorSubject`. Unlike `BehaviorSubject`, it only exposes `sendNext` interface, so variable can never terminate or fail.
|
||||
Variable wraps a [`Subject`](http://reactivex.io/documentation/subject.html). More specifically it is a `BehaviorSubject`. Unlike `BehaviorSubject`, it only exposes `value` interface, so variable can never terminate or fail.
|
||||
|
||||
It will also broadcast it's current value immediately on subscription.
|
||||
|
||||
|
|
@ -928,7 +971,7 @@ variable
|
|||
|
||||
println("Before send 1")
|
||||
|
||||
variable.sendNext(1)
|
||||
variable.value = 1
|
||||
|
||||
println("Before second subscription ---")
|
||||
|
||||
|
|
@ -937,7 +980,7 @@ variable
|
|||
println("Second \(n)")
|
||||
}
|
||||
|
||||
variable.sendNext(2)
|
||||
variable.value = 2
|
||||
|
||||
println("End ---")
|
||||
```
|
||||
|
|
@ -1048,7 +1091,7 @@ To fix this you need to add `observeOn(MainScheduler.sharedInstance)`.
|
|||
|
||||
You can't bind failure to UIKit controls because that is undefined behavior.
|
||||
|
||||
If you don't know if `Observable` can fail, you can ensure it can't fail using `catchErrorResumeNext(valueThatIsReturnedWhenErrorHappens)`, **but after an error happens the underlying sequence will still complete**.
|
||||
If you don't know if `Observable` can fail, you can ensure it can't fail using `catchErrorJustReturn(valueThatIsReturnedWhenErrorHappens)`, **but after an error happens the underlying sequence will still complete**.
|
||||
|
||||
If the wanted behavior is for underlying sequence to continue producing elements, some version of `retry` operator is needed.
|
||||
|
||||
|
|
@ -1066,7 +1109,7 @@ let searchResults = searchText
|
|||
API.getSearchResults(query)
|
||||
.retry(3)
|
||||
.startWith([]) // clears results on new search term
|
||||
.catchErrorResumeNext([])
|
||||
.catchErrorJustReturn([])
|
||||
}
|
||||
.switchLatest()
|
||||
.shareReplay(1) // <- notice the `shareReplay` operator
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ The migration should be pretty straightforward. The changes are mostly cosmetic,
|
|||
|
||||
* Find replace all `>- ` to `.`
|
||||
* Find replace all "variable" to "shareReplay(1)"
|
||||
* Find replace all "catch" to "catchErrorResumeNext"
|
||||
* Find replace all "catch" to "catchErrorJustReturn"
|
||||
* Find replace all "returnElement" to "just"
|
||||
* Since we've moved from `>-` to `.`, free functions are now methods, so it's `.switchLatest()`, `.distinctUntilChanged()`, ... instead of `>- switchLatest`, `>- distinctUntilChanged`
|
||||
* we've moved from free functions to extensions so it's now `[a, b, c].concat()`, `.merge()`, ... instead of `concat([a, b, c])`, `merge(sequences)`
|
||||
* Now it's `subscribe { n in ... }.addDisposableTo(disposeBag)` instead of `>- disposeBag.addDisposable`
|
||||
* Method `next` on `Variable` is now `sendNext`
|
||||
* Method `next` on `Variable` is now `value` setter
|
||||
* If you want to use `tableViews`/`collectionViews`, this is the basic use case now
|
||||
|
||||
```swift
|
||||
|
|
|
|||
|
|
@ -55,9 +55,9 @@ func processFile(path: String, outputPath: String) -> String {
|
|||
functionContentComponents.append("components.append(\(escape(suffix)));\n")
|
||||
}
|
||||
|
||||
functionContentComponents.append("try! \"\".join(components).writeToFile(\"\(outputPath)\", atomically: false, encoding: NSUTF8StringEncoding)")
|
||||
functionContentComponents.append("try! components.joinWithSeparator(\"\").writeToFile(\"\(outputPath)\", atomically: false, encoding: NSUTF8StringEncoding)")
|
||||
|
||||
return "".join(functionContentComponents)
|
||||
return functionContentComponents.joinWithSeparator("")
|
||||
}
|
||||
|
||||
func runCommand(path: String) {
|
||||
|
|
@ -94,7 +94,7 @@ for file in files! {
|
|||
generateAllFiles.append("_ = { () -> Void in\n\(processFile(path, outputPath: outputPath))\n}()\n")
|
||||
}
|
||||
|
||||
let script = "".join(generateAllFiles)
|
||||
let script = generateAllFiles.joinWithSeparator("")
|
||||
let scriptPath = (derivedData as NSString).stringByAppendingPathComponent("_preprocessor.sh")
|
||||
|
||||
do {
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ Writing all of this and properly testing it would be tedious. This is that same
|
|||
API.getSearchResults(query)
|
||||
.retry(3)
|
||||
.startWith([]) // clears results on new search term
|
||||
.catchErrorResumeNext([])
|
||||
.catchErrorJustReturn([])
|
||||
}
|
||||
.switchLatest()
|
||||
.subscribeNext { results in
|
||||
|
|
|
|||
|
|
@ -169,13 +169,13 @@ combine multiple Observables into one by merging their emissions
|
|||
example("merge 1") {
|
||||
let subject1 = PublishSubject<Int>()
|
||||
let subject2 = PublishSubject<Int>()
|
||||
|
||||
|
||||
sequenceOf(subject1, subject2)
|
||||
.merge()
|
||||
.subscribeNext { int in
|
||||
print(int)
|
||||
}
|
||||
|
||||
|
||||
subject1.on(.Next(20))
|
||||
subject1.on(.Next(40))
|
||||
subject1.on(.Next(60))
|
||||
|
|
@ -189,8 +189,8 @@ example("merge 1") {
|
|||
example("merge 2") {
|
||||
let subject1 = PublishSubject<Int>()
|
||||
let subject2 = PublishSubject<Int>()
|
||||
|
||||
sequenceOf(subject1, subject2)
|
||||
|
||||
sequenceOf(subject1, subject2)
|
||||
.merge(maxConcurrent: 2)
|
||||
.subscribe {
|
||||
print($0)
|
||||
|
|
@ -223,25 +223,25 @@ example("switchLatest") {
|
|||
|
||||
// var3 is like an Observable<Observable<Int>>
|
||||
let var3 = Variable(var1)
|
||||
|
||||
|
||||
let d = var3
|
||||
.switchLatest()
|
||||
.subscribe {
|
||||
print($0)
|
||||
}
|
||||
|
||||
var1.sendNext(1)
|
||||
var1.sendNext(2)
|
||||
var1.sendNext(3)
|
||||
var1.sendNext(4)
|
||||
var1.value = 1
|
||||
var1.value = 2
|
||||
var1.value = 3
|
||||
var1.value = 4
|
||||
|
||||
var3.sendNext(var2)
|
||||
var3.value = var2
|
||||
|
||||
var2.sendNext(201)
|
||||
|
||||
var1.sendNext(5)
|
||||
var1.sendNext(6)
|
||||
var1.sendNext(7)
|
||||
var2.value = 201
|
||||
|
||||
var1.value = 5
|
||||
var1.value = 6
|
||||
var1.value = 7
|
||||
}
|
||||
|
||||
//: [Index](Index) - [Next >>](@next)
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ example("catchError 2") {
|
|||
let sequenceThatFails = PublishSubject<Int>()
|
||||
|
||||
sequenceThatFails
|
||||
.catchErrorResumeNext(100)
|
||||
.catchErrorJustReturn(100)
|
||||
.subscribe {
|
||||
print($0)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ example("sequenceOf") {
|
|||
*/
|
||||
|
||||
example("from") {
|
||||
let sequenceFromArray = from([1, 2, 3, 4, 5])
|
||||
let sequenceFromArray = [1, 2, 3, 4, 5].asObservable()
|
||||
|
||||
let subscription = sequenceFromArray
|
||||
.subscribe { event in
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ example("PublishSubject") {
|
|||
*/
|
||||
example("ReplaySubject") {
|
||||
let subject = ReplaySubject<String>.create(bufferSize: 1)
|
||||
|
||||
|
||||
writeSequenceToConsole("1", sequence: subject)
|
||||
subject.on(.Next("a"))
|
||||
subject.on(.Next("b"))
|
||||
|
|
@ -88,11 +88,11 @@ example("BehaviorSubject") {
|
|||
example("Variable") {
|
||||
let variable = Variable("z")
|
||||
writeSequenceToConsole("1", sequence: variable)
|
||||
variable.sendNext("a")
|
||||
variable.sendNext("b")
|
||||
variable.value = "a"
|
||||
variable.value = "b"
|
||||
writeSequenceToConsole("2", sequence: variable)
|
||||
variable.sendNext("c")
|
||||
variable.sendNext("d")
|
||||
variable.value = "c"
|
||||
variable.value = "d"
|
||||
}
|
||||
|
||||
//: [Index](Index) - [Next >>](@next)
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
C8093CC31B8A72BE0088E94D /* AnyObject+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C481B8A72BE0088E94D /* AnyObject+Rx.swift */; };
|
||||
C8093CC41B8A72BE0088E94D /* AnyObject+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C481B8A72BE0088E94D /* AnyObject+Rx.swift */; };
|
||||
C8093CC51B8A72BE0088E94D /* Cancelable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C491B8A72BE0088E94D /* Cancelable.swift */; };
|
||||
C8093CC61B8A72BE0088E94D /* Cancelable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C491B8A72BE0088E94D /* Cancelable.swift */; };
|
||||
C8093CC71B8A72BE0088E94D /* AsyncLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C4B1B8A72BE0088E94D /* AsyncLock.swift */; };
|
||||
|
|
@ -29,8 +27,6 @@
|
|||
C8093CD61B8A72BE0088E94D /* AnonymousDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C541B8A72BE0088E94D /* AnonymousDisposable.swift */; };
|
||||
C8093CD71B8A72BE0088E94D /* BinaryDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C551B8A72BE0088E94D /* BinaryDisposable.swift */; };
|
||||
C8093CD81B8A72BE0088E94D /* BinaryDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C551B8A72BE0088E94D /* BinaryDisposable.swift */; };
|
||||
C8093CD91B8A72BE0088E94D /* BooleanDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C561B8A72BE0088E94D /* BooleanDisposable.swift */; };
|
||||
C8093CDA1B8A72BE0088E94D /* BooleanDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C561B8A72BE0088E94D /* BooleanDisposable.swift */; };
|
||||
C8093CDB1B8A72BE0088E94D /* CompositeDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C571B8A72BE0088E94D /* CompositeDisposable.swift */; };
|
||||
C8093CDC1B8A72BE0088E94D /* CompositeDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C571B8A72BE0088E94D /* CompositeDisposable.swift */; };
|
||||
C8093CDD1B8A72BE0088E94D /* DisposeBag.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C581B8A72BE0088E94D /* DisposeBag.swift */; };
|
||||
|
|
@ -43,8 +39,8 @@
|
|||
C8093CE61B8A72BE0088E94D /* NopDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C5C1B8A72BE0088E94D /* NopDisposable.swift */; };
|
||||
C8093CE71B8A72BE0088E94D /* ScheduledDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C5D1B8A72BE0088E94D /* ScheduledDisposable.swift */; };
|
||||
C8093CE81B8A72BE0088E94D /* ScheduledDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C5D1B8A72BE0088E94D /* ScheduledDisposable.swift */; };
|
||||
C8093CE91B8A72BE0088E94D /* ScopedDispose.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C5E1B8A72BE0088E94D /* ScopedDispose.swift */; };
|
||||
C8093CEA1B8A72BE0088E94D /* ScopedDispose.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C5E1B8A72BE0088E94D /* ScopedDispose.swift */; };
|
||||
C8093CE91B8A72BE0088E94D /* ScopedDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C5E1B8A72BE0088E94D /* ScopedDisposable.swift */; };
|
||||
C8093CEA1B8A72BE0088E94D /* ScopedDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C5E1B8A72BE0088E94D /* ScopedDisposable.swift */; };
|
||||
C8093CEB1B8A72BE0088E94D /* SerialDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C5F1B8A72BE0088E94D /* SerialDisposable.swift */; };
|
||||
C8093CEC1B8A72BE0088E94D /* SerialDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C5F1B8A72BE0088E94D /* SerialDisposable.swift */; };
|
||||
C8093CED1B8A72BE0088E94D /* SingleAssignmentDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C601B8A72BE0088E94D /* SingleAssignmentDisposable.swift */; };
|
||||
|
|
@ -101,8 +97,6 @@
|
|||
C8093D2A1B8A72BE0088E94D /* ObserveOn.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C801B8A72BE0088E94D /* ObserveOn.swift */; };
|
||||
C8093D2B1B8A72BE0088E94D /* ObserveOnSerialDispatchQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C811B8A72BE0088E94D /* ObserveOnSerialDispatchQueue.swift */; };
|
||||
C8093D2C1B8A72BE0088E94D /* ObserveOnSerialDispatchQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C811B8A72BE0088E94D /* ObserveOnSerialDispatchQueue.swift */; };
|
||||
C8093D2D1B8A72BE0088E94D /* ObserveSingleOn.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C821B8A72BE0088E94D /* ObserveSingleOn.swift */; };
|
||||
C8093D2E1B8A72BE0088E94D /* ObserveSingleOn.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C821B8A72BE0088E94D /* ObserveSingleOn.swift */; };
|
||||
C8093D2F1B8A72BE0088E94D /* Producer.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C831B8A72BE0088E94D /* Producer.swift */; };
|
||||
C8093D301B8A72BE0088E94D /* Producer.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C831B8A72BE0088E94D /* Producer.swift */; };
|
||||
C8093D311B8A72BE0088E94D /* Reduce.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093C841B8A72BE0088E94D /* Reduce.swift */; };
|
||||
|
|
@ -173,8 +167,6 @@
|
|||
C8093D741B8A72BE0088E94D /* ObserverBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CA61B8A72BE0088E94D /* ObserverBase.swift */; };
|
||||
C8093D751B8A72BE0088E94D /* SafeObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CA71B8A72BE0088E94D /* SafeObserver.swift */; };
|
||||
C8093D761B8A72BE0088E94D /* SafeObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CA71B8A72BE0088E94D /* SafeObserver.swift */; };
|
||||
C8093D771B8A72BE0088E94D /* ScheduledObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CA81B8A72BE0088E94D /* ScheduledObserver.swift */; };
|
||||
C8093D781B8A72BE0088E94D /* ScheduledObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CA81B8A72BE0088E94D /* ScheduledObserver.swift */; };
|
||||
C8093D791B8A72BE0088E94D /* TailRecursiveSink.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CA91B8A72BE0088E94D /* TailRecursiveSink.swift */; };
|
||||
C8093D7A1B8A72BE0088E94D /* TailRecursiveSink.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CA91B8A72BE0088E94D /* TailRecursiveSink.swift */; };
|
||||
C8093D7B1B8A72BE0088E94D /* ObserverType+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CAA1B8A72BE0088E94D /* ObserverType+Extensions.swift */; };
|
||||
|
|
@ -185,8 +177,6 @@
|
|||
C8093D861B8A72BE0088E94D /* Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CAF1B8A72BE0088E94D /* Rx.swift */; };
|
||||
C8093D871B8A72BE0088E94D /* RxBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CB01B8A72BE0088E94D /* RxBox.swift */; };
|
||||
C8093D881B8A72BE0088E94D /* RxBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CB01B8A72BE0088E94D /* RxBox.swift */; };
|
||||
C8093D891B8A72BE0088E94D /* RxResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CB11B8A72BE0088E94D /* RxResult.swift */; };
|
||||
C8093D8A1B8A72BE0088E94D /* RxResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CB11B8A72BE0088E94D /* RxResult.swift */; };
|
||||
C8093D8D1B8A72BE0088E94D /* Scheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CB31B8A72BE0088E94D /* Scheduler.swift */; };
|
||||
C8093D8E1B8A72BE0088E94D /* Scheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CB31B8A72BE0088E94D /* Scheduler.swift */; };
|
||||
C8093D8F1B8A72BE0088E94D /* ConcurrentDispatchQueueScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CB51B8A72BE0088E94D /* ConcurrentDispatchQueueScheduler.swift */; };
|
||||
|
|
@ -199,8 +189,6 @@
|
|||
C8093D961B8A72BE0088E94D /* OperationQueueScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CB81B8A72BE0088E94D /* OperationQueueScheduler.swift */; };
|
||||
C8093D971B8A72BE0088E94D /* RecursiveScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CB91B8A72BE0088E94D /* RecursiveScheduler.swift */; };
|
||||
C8093D981B8A72BE0088E94D /* RecursiveScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CB91B8A72BE0088E94D /* RecursiveScheduler.swift */; };
|
||||
C8093D991B8A72BE0088E94D /* Scheduler+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CBA1B8A72BE0088E94D /* Scheduler+Extensions.swift */; };
|
||||
C8093D9A1B8A72BE0088E94D /* Scheduler+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CBA1B8A72BE0088E94D /* Scheduler+Extensions.swift */; };
|
||||
C8093D9B1B8A72BE0088E94D /* SchedulerServices+Emulation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CBB1B8A72BE0088E94D /* SchedulerServices+Emulation.swift */; };
|
||||
C8093D9C1B8A72BE0088E94D /* SchedulerServices+Emulation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CBB1B8A72BE0088E94D /* SchedulerServices+Emulation.swift */; };
|
||||
C8093D9D1B8A72BE0088E94D /* SerialDispatchQueueScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093CBC1B8A72BE0088E94D /* SerialDispatchQueueScheduler.swift */; };
|
||||
|
|
@ -272,19 +260,17 @@
|
|||
C8093F501B8A732E0088E94D /* RxCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = C8093ECB1B8A732E0088E94D /* RxCocoa.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C8093F5E1B8A73A20088E94D /* Observable+Blocking.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093F581B8A73A20088E94D /* Observable+Blocking.swift */; };
|
||||
C8093F5F1B8A73A20088E94D /* Observable+Blocking.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8093F581B8A73A20088E94D /* Observable+Blocking.swift */; };
|
||||
C80D342E1B9245A40014629D /* CombineLatest+CollectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C80D342D1B9245A40014629D /* CombineLatest+CollectionType.swift */; settings = {ASSET_TAGS = (); }; };
|
||||
C80D342F1B9245A40014629D /* CombineLatest+CollectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C80D342D1B9245A40014629D /* CombineLatest+CollectionType.swift */; settings = {ASSET_TAGS = (); }; };
|
||||
C80D338F1B91EF9E0014629D /* Observable+CocoaExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C80D338E1B91EF9E0014629D /* Observable+CocoaExtensions.swift */; settings = {ASSET_TAGS = (); }; };
|
||||
C80D33901B91EF9E0014629D /* Observable+CocoaExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C80D338E1B91EF9E0014629D /* Observable+CocoaExtensions.swift */; settings = {ASSET_TAGS = (); }; };
|
||||
C80D33981B922FB00014629D /* ControlEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C80D33931B922FB00014629D /* ControlEvent.swift */; settings = {ASSET_TAGS = (); }; };
|
||||
C80D33991B922FB00014629D /* ControlEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C80D33931B922FB00014629D /* ControlEvent.swift */; settings = {ASSET_TAGS = (); }; };
|
||||
C80D339A1B922FB00014629D /* ControlProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = C80D33941B922FB00014629D /* ControlProperty.swift */; settings = {ASSET_TAGS = (); }; };
|
||||
C80D339B1B922FB00014629D /* ControlProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = C80D33941B922FB00014629D /* ControlProperty.swift */; settings = {ASSET_TAGS = (); }; };
|
||||
C88254151B8A752B00B02D69 /* CoreDataEntityEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C88253EF1B8A752B00B02D69 /* CoreDataEntityEvent.swift */; };
|
||||
C80D342E1B9245A40014629D /* CombineLatest+CollectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C80D342D1B9245A40014629D /* CombineLatest+CollectionType.swift */; settings = {ASSET_TAGS = (); }; };
|
||||
C80D342F1B9245A40014629D /* CombineLatest+CollectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C80D342D1B9245A40014629D /* CombineLatest+CollectionType.swift */; settings = {ASSET_TAGS = (); }; };
|
||||
C88254161B8A752B00B02D69 /* RxCollectionViewReactiveArrayDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = C88253F11B8A752B00B02D69 /* RxCollectionViewReactiveArrayDataSource.swift */; };
|
||||
C88254171B8A752B00B02D69 /* RxTableViewReactiveArrayDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = C88253F21B8A752B00B02D69 /* RxTableViewReactiveArrayDataSource.swift */; };
|
||||
C88254181B8A752B00B02D69 /* ItemEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = C88253F41B8A752B00B02D69 /* ItemEvents.swift */; };
|
||||
C88254191B8A752B00B02D69 /* NSManagedObjectContext+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = C88253F51B8A752B00B02D69 /* NSManagedObjectContext+Rx.swift */; };
|
||||
C882541A1B8A752B00B02D69 /* RxCollectionViewDataSourceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C88253F71B8A752B00B02D69 /* RxCollectionViewDataSourceType.swift */; };
|
||||
C882541B1B8A752B00B02D69 /* RxTableViewDataSourceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C88253F81B8A752B00B02D69 /* RxTableViewDataSourceType.swift */; };
|
||||
C882541C1B8A752B00B02D69 /* RxActionSheetDelegateProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = C88253FA1B8A752B00B02D69 /* RxActionSheetDelegateProxy.swift */; };
|
||||
|
|
@ -340,7 +326,6 @@
|
|||
C80939E71B8A71840088E94D /* RxCocoa.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RxCocoa.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C8093BC71B8A71F00088E94D /* RxBlocking.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RxBlocking.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C8093C451B8A71FC0088E94D /* RxBlocking.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RxBlocking.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C8093C481B8A72BE0088E94D /* AnyObject+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AnyObject+Rx.swift"; sourceTree = "<group>"; };
|
||||
C8093C491B8A72BE0088E94D /* Cancelable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cancelable.swift; sourceTree = "<group>"; };
|
||||
C8093C4B1B8A72BE0088E94D /* AsyncLock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsyncLock.swift; sourceTree = "<group>"; };
|
||||
C8093C4C1B8A72BE0088E94D /* Lock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Lock.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -351,7 +336,6 @@
|
|||
C8093C521B8A72BE0088E94D /* Disposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Disposable.swift; sourceTree = "<group>"; };
|
||||
C8093C541B8A72BE0088E94D /* AnonymousDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnonymousDisposable.swift; sourceTree = "<group>"; };
|
||||
C8093C551B8A72BE0088E94D /* BinaryDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BinaryDisposable.swift; sourceTree = "<group>"; };
|
||||
C8093C561B8A72BE0088E94D /* BooleanDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BooleanDisposable.swift; sourceTree = "<group>"; };
|
||||
C8093C571B8A72BE0088E94D /* CompositeDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompositeDisposable.swift; sourceTree = "<group>"; };
|
||||
C8093C581B8A72BE0088E94D /* DisposeBag.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DisposeBag.swift; sourceTree = "<group>"; };
|
||||
C8093C591B8A72BE0088E94D /* DisposeBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DisposeBase.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -359,7 +343,7 @@
|
|||
C8093C5B1B8A72BE0088E94D /* NAryDisposable.tt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = NAryDisposable.tt; sourceTree = "<group>"; };
|
||||
C8093C5C1B8A72BE0088E94D /* NopDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NopDisposable.swift; sourceTree = "<group>"; };
|
||||
C8093C5D1B8A72BE0088E94D /* ScheduledDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScheduledDisposable.swift; sourceTree = "<group>"; };
|
||||
C8093C5E1B8A72BE0088E94D /* ScopedDispose.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScopedDispose.swift; sourceTree = "<group>"; };
|
||||
C8093C5E1B8A72BE0088E94D /* ScopedDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScopedDisposable.swift; sourceTree = "<group>"; };
|
||||
C8093C5F1B8A72BE0088E94D /* SerialDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SerialDisposable.swift; sourceTree = "<group>"; };
|
||||
C8093C601B8A72BE0088E94D /* SingleAssignmentDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleAssignmentDisposable.swift; sourceTree = "<group>"; };
|
||||
C8093C611B8A72BE0088E94D /* StableCompositeDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StableCompositeDisposable.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -390,7 +374,6 @@
|
|||
C8093C7E1B8A72BE0088E94D /* Multicast.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Multicast.swift; sourceTree = "<group>"; };
|
||||
C8093C801B8A72BE0088E94D /* ObserveOn.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObserveOn.swift; sourceTree = "<group>"; };
|
||||
C8093C811B8A72BE0088E94D /* ObserveOnSerialDispatchQueue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObserveOnSerialDispatchQueue.swift; sourceTree = "<group>"; };
|
||||
C8093C821B8A72BE0088E94D /* ObserveSingleOn.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObserveSingleOn.swift; sourceTree = "<group>"; };
|
||||
C8093C831B8A72BE0088E94D /* Producer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Producer.swift; sourceTree = "<group>"; };
|
||||
C8093C841B8A72BE0088E94D /* Reduce.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Reduce.swift; sourceTree = "<group>"; };
|
||||
C8093C851B8A72BE0088E94D /* RefCount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RefCount.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -427,20 +410,17 @@
|
|||
C8093CA51B8A72BE0088E94D /* NopObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NopObserver.swift; sourceTree = "<group>"; };
|
||||
C8093CA61B8A72BE0088E94D /* ObserverBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObserverBase.swift; sourceTree = "<group>"; };
|
||||
C8093CA71B8A72BE0088E94D /* SafeObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SafeObserver.swift; sourceTree = "<group>"; };
|
||||
C8093CA81B8A72BE0088E94D /* ScheduledObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScheduledObserver.swift; sourceTree = "<group>"; };
|
||||
C8093CA91B8A72BE0088E94D /* TailRecursiveSink.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TailRecursiveSink.swift; sourceTree = "<group>"; };
|
||||
C8093CAA1B8A72BE0088E94D /* ObserverType+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ObserverType+Extensions.swift"; sourceTree = "<group>"; };
|
||||
C8093CAB1B8A72BE0088E94D /* ObserverType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObserverType.swift; sourceTree = "<group>"; };
|
||||
C8093CAF1B8A72BE0088E94D /* Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Rx.swift; sourceTree = "<group>"; };
|
||||
C8093CB01B8A72BE0088E94D /* RxBox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxBox.swift; sourceTree = "<group>"; };
|
||||
C8093CB11B8A72BE0088E94D /* RxResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxResult.swift; sourceTree = "<group>"; };
|
||||
C8093CB31B8A72BE0088E94D /* Scheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Scheduler.swift; sourceTree = "<group>"; };
|
||||
C8093CB51B8A72BE0088E94D /* ConcurrentDispatchQueueScheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConcurrentDispatchQueueScheduler.swift; sourceTree = "<group>"; };
|
||||
C8093CB61B8A72BE0088E94D /* DispatchQueueSchedulerPriority.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DispatchQueueSchedulerPriority.swift; sourceTree = "<group>"; };
|
||||
C8093CB71B8A72BE0088E94D /* MainScheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainScheduler.swift; sourceTree = "<group>"; };
|
||||
C8093CB81B8A72BE0088E94D /* OperationQueueScheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperationQueueScheduler.swift; sourceTree = "<group>"; };
|
||||
C8093CB91B8A72BE0088E94D /* RecursiveScheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecursiveScheduler.swift; sourceTree = "<group>"; };
|
||||
C8093CBA1B8A72BE0088E94D /* Scheduler+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Scheduler+Extensions.swift"; sourceTree = "<group>"; };
|
||||
C8093CBB1B8A72BE0088E94D /* SchedulerServices+Emulation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SchedulerServices+Emulation.swift"; sourceTree = "<group>"; };
|
||||
C8093CBC1B8A72BE0088E94D /* SerialDispatchQueueScheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SerialDispatchQueueScheduler.swift; sourceTree = "<group>"; };
|
||||
C8093CBE1B8A72BE0088E94D /* BehaviorSubject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BehaviorSubject.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -481,15 +461,13 @@
|
|||
C8093ECB1B8A732E0088E94D /* RxCocoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RxCocoa.h; sourceTree = "<group>"; };
|
||||
C8093F581B8A73A20088E94D /* Observable+Blocking.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Observable+Blocking.swift"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
||||
C8093F591B8A73A20088E94D /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
|
||||
C80D342D1B9245A40014629D /* CombineLatest+CollectionType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CombineLatest+CollectionType.swift"; sourceTree = "<group>"; };
|
||||
C80D338E1B91EF9E0014629D /* Observable+CocoaExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Observable+CocoaExtensions.swift"; sourceTree = "<group>"; };
|
||||
C80D33931B922FB00014629D /* ControlEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ControlEvent.swift; sourceTree = "<group>"; };
|
||||
C80D33941B922FB00014629D /* ControlProperty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ControlProperty.swift; sourceTree = "<group>"; };
|
||||
C88253EF1B8A752B00B02D69 /* CoreDataEntityEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataEntityEvent.swift; sourceTree = "<group>"; };
|
||||
C80D342D1B9245A40014629D /* CombineLatest+CollectionType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CombineLatest+CollectionType.swift"; sourceTree = "<group>"; };
|
||||
C88253F11B8A752B00B02D69 /* RxCollectionViewReactiveArrayDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxCollectionViewReactiveArrayDataSource.swift; sourceTree = "<group>"; };
|
||||
C88253F21B8A752B00B02D69 /* RxTableViewReactiveArrayDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxTableViewReactiveArrayDataSource.swift; sourceTree = "<group>"; };
|
||||
C88253F41B8A752B00B02D69 /* ItemEvents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ItemEvents.swift; sourceTree = "<group>"; };
|
||||
C88253F51B8A752B00B02D69 /* NSManagedObjectContext+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectContext+Rx.swift"; sourceTree = "<group>"; };
|
||||
C88253F71B8A752B00B02D69 /* RxCollectionViewDataSourceType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxCollectionViewDataSourceType.swift; sourceTree = "<group>"; };
|
||||
C88253F81B8A752B00B02D69 /* RxTableViewDataSourceType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxTableViewDataSourceType.swift; sourceTree = "<group>"; };
|
||||
C88253FA1B8A752B00B02D69 /* RxActionSheetDelegateProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxActionSheetDelegateProxy.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -584,7 +562,6 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
C8093C661B8A72BE0088E94D /* Info.plist */,
|
||||
C8093C481B8A72BE0088E94D /* AnyObject+Rx.swift */,
|
||||
C8093C491B8A72BE0088E94D /* Cancelable.swift */,
|
||||
C8093C4D1B8A72BE0088E94D /* ConnectableObservableType.swift */,
|
||||
C8093C521B8A72BE0088E94D /* Disposable.swift */,
|
||||
|
|
@ -600,7 +577,6 @@
|
|||
C8093CAA1B8A72BE0088E94D /* ObserverType+Extensions.swift */,
|
||||
C8093CAF1B8A72BE0088E94D /* Rx.swift */,
|
||||
C8093CB01B8A72BE0088E94D /* RxBox.swift */,
|
||||
C8093CB11B8A72BE0088E94D /* RxResult.swift */,
|
||||
C8093CB31B8A72BE0088E94D /* Scheduler.swift */,
|
||||
C8093C4A1B8A72BE0088E94D /* Concurrency */,
|
||||
C8093C4E1B8A72BE0088E94D /* DataStructures */,
|
||||
|
|
@ -637,7 +613,6 @@
|
|||
children = (
|
||||
C8093C541B8A72BE0088E94D /* AnonymousDisposable.swift */,
|
||||
C8093C551B8A72BE0088E94D /* BinaryDisposable.swift */,
|
||||
C8093C561B8A72BE0088E94D /* BooleanDisposable.swift */,
|
||||
C8093C571B8A72BE0088E94D /* CompositeDisposable.swift */,
|
||||
C8093C581B8A72BE0088E94D /* DisposeBag.swift */,
|
||||
C8093C591B8A72BE0088E94D /* DisposeBase.swift */,
|
||||
|
|
@ -645,7 +620,7 @@
|
|||
C8093C5B1B8A72BE0088E94D /* NAryDisposable.tt */,
|
||||
C8093C5C1B8A72BE0088E94D /* NopDisposable.swift */,
|
||||
C8093C5D1B8A72BE0088E94D /* ScheduledDisposable.swift */,
|
||||
C8093C5E1B8A72BE0088E94D /* ScopedDispose.swift */,
|
||||
C8093C5E1B8A72BE0088E94D /* ScopedDisposable.swift */,
|
||||
C8093C5F1B8A72BE0088E94D /* SerialDisposable.swift */,
|
||||
C8093C601B8A72BE0088E94D /* SingleAssignmentDisposable.swift */,
|
||||
C8093C611B8A72BE0088E94D /* StableCompositeDisposable.swift */,
|
||||
|
|
@ -695,7 +670,6 @@
|
|||
C8093C7E1B8A72BE0088E94D /* Multicast.swift */,
|
||||
C8093C801B8A72BE0088E94D /* ObserveOn.swift */,
|
||||
C8093C811B8A72BE0088E94D /* ObserveOnSerialDispatchQueue.swift */,
|
||||
C8093C821B8A72BE0088E94D /* ObserveSingleOn.swift */,
|
||||
C8093C831B8A72BE0088E94D /* Producer.swift */,
|
||||
C8093C841B8A72BE0088E94D /* Reduce.swift */,
|
||||
C8093C851B8A72BE0088E94D /* RefCount.swift */,
|
||||
|
|
@ -733,7 +707,6 @@
|
|||
C8093CA51B8A72BE0088E94D /* NopObserver.swift */,
|
||||
C8093CA61B8A72BE0088E94D /* ObserverBase.swift */,
|
||||
C8093CA71B8A72BE0088E94D /* SafeObserver.swift */,
|
||||
C8093CA81B8A72BE0088E94D /* ScheduledObserver.swift */,
|
||||
C8093CA91B8A72BE0088E94D /* TailRecursiveSink.swift */,
|
||||
);
|
||||
path = Observers;
|
||||
|
|
@ -747,7 +720,6 @@
|
|||
C8093CB71B8A72BE0088E94D /* MainScheduler.swift */,
|
||||
C8093CB81B8A72BE0088E94D /* OperationQueueScheduler.swift */,
|
||||
C8093CB91B8A72BE0088E94D /* RecursiveScheduler.swift */,
|
||||
C8093CBA1B8A72BE0088E94D /* Scheduler+Extensions.swift */,
|
||||
C8093CBB1B8A72BE0088E94D /* SchedulerServices+Emulation.swift */,
|
||||
C8093CBC1B8A72BE0088E94D /* SerialDispatchQueueScheduler.swift */,
|
||||
C8C3DA0E1B939767004D233E /* CurrentThreadScheduler.swift */,
|
||||
|
|
@ -870,10 +842,8 @@
|
|||
C88253EE1B8A752B00B02D69 /* iOS */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C88253EF1B8A752B00B02D69 /* CoreDataEntityEvent.swift */,
|
||||
C88253F01B8A752B00B02D69 /* DataSources */,
|
||||
C88253F31B8A752B00B02D69 /* Events */,
|
||||
C88253F51B8A752B00B02D69 /* NSManagedObjectContext+Rx.swift */,
|
||||
C88253F61B8A752B00B02D69 /* Protocols */,
|
||||
C88253F91B8A752B00B02D69 /* Proxies */,
|
||||
C88254031B8A752B00B02D69 /* UIActionSheet+Rx.swift */,
|
||||
|
|
@ -1238,8 +1208,6 @@
|
|||
C882541F1B8A752B00B02D69 /* RxCollectionViewDelegateProxy.swift in Sources */,
|
||||
C88254201B8A752B00B02D69 /* RxScrollViewDelegateProxy.swift in Sources */,
|
||||
C882542E1B8A752B00B02D69 /* UILabel+Rx.swift in Sources */,
|
||||
C88254191B8A752B00B02D69 /* NSManagedObjectContext+Rx.swift in Sources */,
|
||||
C88254151B8A752B00B02D69 /* CoreDataEntityEvent.swift in Sources */,
|
||||
C88254211B8A752B00B02D69 /* RxSearchBarDelegateProxy.swift in Sources */,
|
||||
C882541D1B8A752B00B02D69 /* RxAlertViewDelegateProxy.swift in Sources */,
|
||||
C80D338F1B91EF9E0014629D /* Observable+CocoaExtensions.swift in Sources */,
|
||||
|
|
@ -1331,22 +1299,18 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C8093CDA1B8A72BE0088E94D /* BooleanDisposable.swift in Sources */,
|
||||
C8093D5A1B8A72BE0088E94D /* Observable+Creation.swift in Sources */,
|
||||
C8093CCC1B8A72BE0088E94D /* ConnectableObservableType.swift in Sources */,
|
||||
C8C3DA041B9390C4004D233E /* Just.swift in Sources */,
|
||||
C8093CE61B8A72BE0088E94D /* NopDisposable.swift in Sources */,
|
||||
C8093CD41B8A72BE0088E94D /* Disposable.swift in Sources */,
|
||||
C8093CC41B8A72BE0088E94D /* AnyObject+Rx.swift in Sources */,
|
||||
C8093CEE1B8A72BE0088E94D /* SingleAssignmentDisposable.swift in Sources */,
|
||||
C8093D681B8A72BE0088E94D /* Observer.swift in Sources */,
|
||||
C8C3DA0A1B93941E004D233E /* FailWith.swift in Sources */,
|
||||
C8093D781B8A72BE0088E94D /* ScheduledObserver.swift in Sources */,
|
||||
C8093D9C1B8A72BE0088E94D /* SchedulerServices+Emulation.swift in Sources */,
|
||||
C8093D6A1B8A72BE0088E94D /* ObserverOf.swift in Sources */,
|
||||
C8093D3C1B8A72BE0088E94D /* Skip.swift in Sources */,
|
||||
C8093CF01B8A72BE0088E94D /* StableCompositeDisposable.swift in Sources */,
|
||||
C8093D2E1B8A72BE0088E94D /* ObserveSingleOn.swift in Sources */,
|
||||
C8093D4E1B8A72BE0088E94D /* Zip+arity.swift in Sources */,
|
||||
C8093D4C1B8A72BE0088E94D /* Timer.swift in Sources */,
|
||||
C8C3DA071B9393AC004D233E /* Empty.swift in Sources */,
|
||||
|
|
@ -1370,14 +1334,12 @@
|
|||
C8093D621B8A72BE0088E94D /* Observable+StandardSequenceOperators.swift in Sources */,
|
||||
C8093D1A1B8A72BE0088E94D /* DistinctUntilChanged.swift in Sources */,
|
||||
C8093D561B8A72BE0088E94D /* Observable+Binding.swift in Sources */,
|
||||
C8093D8A1B8A72BE0088E94D /* RxResult.swift in Sources */,
|
||||
C8093D7A1B8A72BE0088E94D /* TailRecursiveSink.swift in Sources */,
|
||||
C8093CC81B8A72BE0088E94D /* AsyncLock.swift in Sources */,
|
||||
C8093D9A1B8A72BE0088E94D /* Scheduler+Extensions.swift in Sources */,
|
||||
C8093CD81B8A72BE0088E94D /* BinaryDisposable.swift in Sources */,
|
||||
C8093D2A1B8A72BE0088E94D /* ObserveOn.swift in Sources */,
|
||||
C8093D361B8A72BE0088E94D /* Sample.swift in Sources */,
|
||||
C8093CEA1B8A72BE0088E94D /* ScopedDispose.swift in Sources */,
|
||||
C8093CEA1B8A72BE0088E94D /* ScopedDisposable.swift in Sources */,
|
||||
C8093D261B8A72BE0088E94D /* Multicast.swift in Sources */,
|
||||
C8C3DA101B939767004D233E /* CurrentThreadScheduler.swift in Sources */,
|
||||
C8093D861B8A72BE0088E94D /* Rx.swift in Sources */,
|
||||
|
|
@ -1450,22 +1412,18 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C8093CD91B8A72BE0088E94D /* BooleanDisposable.swift in Sources */,
|
||||
C8093D591B8A72BE0088E94D /* Observable+Creation.swift in Sources */,
|
||||
C8093CCB1B8A72BE0088E94D /* ConnectableObservableType.swift in Sources */,
|
||||
C8C3DA031B9390C4004D233E /* Just.swift in Sources */,
|
||||
C8093CE51B8A72BE0088E94D /* NopDisposable.swift in Sources */,
|
||||
C8093CD31B8A72BE0088E94D /* Disposable.swift in Sources */,
|
||||
C8093CC31B8A72BE0088E94D /* AnyObject+Rx.swift in Sources */,
|
||||
C8093CED1B8A72BE0088E94D /* SingleAssignmentDisposable.swift in Sources */,
|
||||
C8093D671B8A72BE0088E94D /* Observer.swift in Sources */,
|
||||
C8C3DA091B93941E004D233E /* FailWith.swift in Sources */,
|
||||
C8093D771B8A72BE0088E94D /* ScheduledObserver.swift in Sources */,
|
||||
C8093D9B1B8A72BE0088E94D /* SchedulerServices+Emulation.swift in Sources */,
|
||||
C8093D691B8A72BE0088E94D /* ObserverOf.swift in Sources */,
|
||||
C8093D3B1B8A72BE0088E94D /* Skip.swift in Sources */,
|
||||
C8093CEF1B8A72BE0088E94D /* StableCompositeDisposable.swift in Sources */,
|
||||
C8093D2D1B8A72BE0088E94D /* ObserveSingleOn.swift in Sources */,
|
||||
C8093D4D1B8A72BE0088E94D /* Zip+arity.swift in Sources */,
|
||||
C8093D4B1B8A72BE0088E94D /* Timer.swift in Sources */,
|
||||
C8C3DA061B9393AC004D233E /* Empty.swift in Sources */,
|
||||
|
|
@ -1489,14 +1447,12 @@
|
|||
C8093D611B8A72BE0088E94D /* Observable+StandardSequenceOperators.swift in Sources */,
|
||||
C8093D191B8A72BE0088E94D /* DistinctUntilChanged.swift in Sources */,
|
||||
C8093D551B8A72BE0088E94D /* Observable+Binding.swift in Sources */,
|
||||
C8093D891B8A72BE0088E94D /* RxResult.swift in Sources */,
|
||||
C8093D791B8A72BE0088E94D /* TailRecursiveSink.swift in Sources */,
|
||||
C8093CC71B8A72BE0088E94D /* AsyncLock.swift in Sources */,
|
||||
C8093D991B8A72BE0088E94D /* Scheduler+Extensions.swift in Sources */,
|
||||
C8093CD71B8A72BE0088E94D /* BinaryDisposable.swift in Sources */,
|
||||
C8093D291B8A72BE0088E94D /* ObserveOn.swift in Sources */,
|
||||
C8093D351B8A72BE0088E94D /* Sample.swift in Sources */,
|
||||
C8093CE91B8A72BE0088E94D /* ScopedDispose.swift in Sources */,
|
||||
C8093CE91B8A72BE0088E94D /* ScopedDisposable.swift in Sources */,
|
||||
C8093D251B8A72BE0088E94D /* Multicast.swift in Sources */,
|
||||
C8C3DA0F1B939767004D233E /* CurrentThreadScheduler.swift in Sources */,
|
||||
C8093D851B8A72BE0088E94D /* Rx.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,13 @@ import RxSwift
|
|||
#endif
|
||||
|
||||
extension ObservableType {
|
||||
/**
|
||||
Blocks current thread until sequence terminates.
|
||||
|
||||
If sequence terminates with error, terminating error will be thrown.
|
||||
|
||||
- returns: All elements of sequence.
|
||||
*/
|
||||
public func toArray() throws -> [E] {
|
||||
let condition = NSCondition()
|
||||
|
||||
|
|
@ -21,7 +28,7 @@ extension ObservableType {
|
|||
|
||||
var ended = false
|
||||
|
||||
self.subscribeSafe(AnonymousObserver { e in
|
||||
self.subscribe { e in
|
||||
switch e {
|
||||
case .Next(let element):
|
||||
elements.append(element)
|
||||
|
|
@ -37,7 +44,7 @@ extension ObservableType {
|
|||
condition.signal()
|
||||
condition.unlock()
|
||||
}
|
||||
})
|
||||
}
|
||||
condition.lock()
|
||||
while !ended {
|
||||
condition.wait()
|
||||
|
|
@ -53,6 +60,13 @@ extension ObservableType {
|
|||
}
|
||||
|
||||
extension ObservableType {
|
||||
/**
|
||||
Blocks current thread until sequence produces first element.
|
||||
|
||||
If sequence terminates with error before producing first element, terminating error will be thrown.
|
||||
|
||||
- returns: First element of sequence. If sequence is empty `nil` is returned.
|
||||
*/
|
||||
public func first() throws -> E? {
|
||||
let condition = NSCondition()
|
||||
|
||||
|
|
@ -64,7 +78,7 @@ extension ObservableType {
|
|||
|
||||
let d = SingleAssignmentDisposable()
|
||||
|
||||
d.disposable = self.subscribeSafe(AnonymousObserver { e in
|
||||
d.disposable = self.subscribe { e in
|
||||
switch e {
|
||||
case .Next(let e):
|
||||
if element == nil {
|
||||
|
|
@ -81,7 +95,7 @@ extension ObservableType {
|
|||
ended = true
|
||||
condition.signal()
|
||||
condition.unlock()
|
||||
})
|
||||
}
|
||||
|
||||
condition.lock()
|
||||
while !ended {
|
||||
|
|
@ -99,6 +113,13 @@ extension ObservableType {
|
|||
}
|
||||
|
||||
extension ObservableType {
|
||||
/**
|
||||
Blocks current thread until sequence terminates.
|
||||
|
||||
If sequence terminates with error, terminating error will be thrown.
|
||||
|
||||
- returns: Last element in the sequence. If sequence is empty `nil` is returned.
|
||||
*/
|
||||
public func last() throws -> E? {
|
||||
let condition = NSCondition()
|
||||
|
||||
|
|
@ -110,7 +131,7 @@ extension ObservableType {
|
|||
|
||||
let d = SingleAssignmentDisposable()
|
||||
|
||||
d.disposable = self.subscribeSafe(AnonymousObserver { e in
|
||||
d.disposable = self.subscribe { e in
|
||||
switch e {
|
||||
case .Next(let e):
|
||||
element = e
|
||||
|
|
@ -125,7 +146,7 @@ extension ObservableType {
|
|||
ended = true
|
||||
condition.signal()
|
||||
condition.unlock()
|
||||
})
|
||||
}
|
||||
|
||||
condition.lock()
|
||||
while !ended {
|
||||
|
|
|
|||
|
|
@ -7,14 +7,17 @@ Set of blocking operators for easy unit testing.
|
|||
|
||||
|
||||
```swift
|
||||
public func toArray<E>(source: Observable<E>)
|
||||
-> RxResult<[E]> {}
|
||||
extension ObservableType {
|
||||
public func toArray() throws -> [E] {}
|
||||
}
|
||||
|
||||
public func first<E>(source: Observable<E>)
|
||||
-> RxResult<E?> {}
|
||||
extension ObservableType {
|
||||
public func first() throws -> E? {}
|
||||
}
|
||||
|
||||
public func last<E>(source: Observable<E>)
|
||||
-> RxResult<E?> {}
|
||||
extension ObservableType {
|
||||
public func last() throws -> E? {}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ extension CLLocationManager {
|
|||
|
||||
// MARK: Responding to Location Events
|
||||
|
||||
/**
|
||||
Reactive wrapper for `delegate` method.
|
||||
*/
|
||||
public var rx_didUpdateLocations: Observable<[CLLocation]!> {
|
||||
return rx_delegate.observe("locationManager:didUpdateLocations:")
|
||||
.map { a in
|
||||
|
|
@ -27,6 +30,9 @@ extension CLLocationManager {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Reactive wrapper for `delegate` method.
|
||||
*/
|
||||
public var rx_didFailWithError: Observable<NSError!> {
|
||||
return rx_delegate.observe("locationManager:didFailWithError:")
|
||||
.map { a in
|
||||
|
|
@ -34,6 +40,9 @@ extension CLLocationManager {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Reactive wrapper for `delegate` method.
|
||||
*/
|
||||
public var rx_didFinishDeferredUpdatesWithError: Observable<NSError!> {
|
||||
return rx_delegate.observe("locationManager:didFinishDeferredUpdatesWithError:")
|
||||
.map { a in
|
||||
|
|
@ -43,6 +52,9 @@ extension CLLocationManager {
|
|||
|
||||
// MARK: Pausing Location Updates
|
||||
|
||||
/**
|
||||
Reactive wrapper for `delegate` method.
|
||||
*/
|
||||
public var rx_didPauseLocationUpdates: Observable<Void> {
|
||||
return rx_delegate.observe("locationManagerDidPauseLocationUpdates:")
|
||||
.map { _ in
|
||||
|
|
@ -50,6 +62,9 @@ extension CLLocationManager {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Reactive wrapper for `delegate` method.
|
||||
*/
|
||||
public var rx_didResumeLocationUpdates: Observable<Void> {
|
||||
return rx_delegate.observe("locationManagerDidResumeLocationUpdates:")
|
||||
.map { _ in
|
||||
|
|
@ -59,6 +74,9 @@ extension CLLocationManager {
|
|||
|
||||
// MARK: Responding to Heading Events
|
||||
|
||||
/**
|
||||
Reactive wrapper for `delegate` method.
|
||||
*/
|
||||
public var rx_didUpdateHeading: Observable<CLHeading!> {
|
||||
return rx_delegate.observe("locationManager:didUpdateHeading:")
|
||||
.map { a in
|
||||
|
|
@ -68,6 +86,9 @@ extension CLLocationManager {
|
|||
|
||||
// MARK: Responding to Region Events
|
||||
|
||||
/**
|
||||
Reactive wrapper for `delegate` method.
|
||||
*/
|
||||
public var rx_didEnterRegion: Observable<CLRegion!> {
|
||||
return rx_delegate.observe("locationManager:didEnterRegion:")
|
||||
.map { a in
|
||||
|
|
@ -75,6 +96,9 @@ extension CLLocationManager {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Reactive wrapper for `delegate` method.
|
||||
*/
|
||||
public var rx_didExitRegion: Observable<CLRegion!> {
|
||||
return rx_delegate.observe("locationManager:didExitRegion:")
|
||||
.map { a in
|
||||
|
|
@ -82,6 +106,9 @@ extension CLLocationManager {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Reactive wrapper for `delegate` method.
|
||||
*/
|
||||
@available(OSX 10.10, *)
|
||||
public var rx_didDetermineStateForRegion: Observable<(state: CLRegionState, region: CLRegion!)> {
|
||||
return rx_delegate.observe("locationManager:didDetermineState:forRegion:")
|
||||
|
|
@ -90,6 +117,9 @@ extension CLLocationManager {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Reactive wrapper for `delegate` method.
|
||||
*/
|
||||
public var rx_monitoringDidFailForRegionWithError: Observable<(region: CLRegion!, error: NSError!)> {
|
||||
return rx_delegate.observe("locationManager:monitoringDidFailForRegion:withError:")
|
||||
.map { a in
|
||||
|
|
@ -97,6 +127,9 @@ extension CLLocationManager {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Reactive wrapper for `delegate` method.
|
||||
*/
|
||||
public var rx_didStartMonitoringForRegion: Observable<CLRegion!> {
|
||||
return rx_delegate.observe("locationManager:didStartMonitoringForRegion:")
|
||||
.map { a in
|
||||
|
|
@ -108,6 +141,9 @@ extension CLLocationManager {
|
|||
|
||||
#if os(iOS)
|
||||
|
||||
/**
|
||||
Reactive wrapper for `delegate` method.
|
||||
*/
|
||||
public var rx_didRangeBeaconsInRegion: Observable<(beacons: [CLBeacon]!, region: CLBeaconRegion!)> {
|
||||
return rx_delegate.observe("locationManager:didRangeBeacons:inRegion:")
|
||||
.map { a in
|
||||
|
|
@ -115,6 +151,9 @@ extension CLLocationManager {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Reactive wrapper for `delegate` method.
|
||||
*/
|
||||
public var rx_rangingBeaconsDidFailForRegionWithError: Observable<(region: CLBeaconRegion!, error: NSError!)> {
|
||||
return rx_delegate.observe("locationManager:rangingBeaconsDidFailForRegion:withError:")
|
||||
.map { a in
|
||||
|
|
@ -124,6 +163,9 @@ extension CLLocationManager {
|
|||
|
||||
// MARK: Responding to Visit Events
|
||||
|
||||
/**
|
||||
Reactive wrapper for `delegate` method.
|
||||
*/
|
||||
@available(iOS 8.0, *)
|
||||
public var rx_didVisit: Observable<CLVisit!> {
|
||||
return rx_delegate.observe("locationManager:didVisit:")
|
||||
|
|
@ -136,6 +178,9 @@ extension CLLocationManager {
|
|||
|
||||
// MARK: Responding to Authorization Changes
|
||||
|
||||
/**
|
||||
Reactive wrapper for `delegate` method.
|
||||
*/
|
||||
public var rx_didChangeAuthorizationStatus: Observable<CLAuthorizationStatus?> {
|
||||
return rx_delegate.observe("locationManager:didChangeAuthorizationStatus:")
|
||||
.map { a in
|
||||
|
|
|
|||
|
|
@ -11,8 +11,14 @@ import Foundation
|
|||
import RxSwift
|
||||
#endif
|
||||
|
||||
protocol ControlEventType : ObservableType {
|
||||
typealias E
|
||||
/**
|
||||
Protocol that enables extension of `ControlEvent`.
|
||||
*/
|
||||
public protocol ControlEventType : ObservableType {
|
||||
|
||||
/**
|
||||
- returns: `ControlEvent` interface
|
||||
*/
|
||||
func asControlEvent() -> ControlEvent<E>
|
||||
}
|
||||
|
||||
|
|
@ -36,14 +42,26 @@ public struct ControlEvent<PropertyType> : ControlEventType {
|
|||
self.source = source
|
||||
}
|
||||
|
||||
/**
|
||||
Subscribes an observer to control events.
|
||||
|
||||
- parameter observer: Observer to subscribe to events.
|
||||
- returns: Disposable object that can be used to unsubscribe the observer from receiving control events.
|
||||
*/
|
||||
public func subscribe<O : ObserverType where O.E == E>(observer: O) -> Disposable {
|
||||
return self.source.subscribe(observer)
|
||||
}
|
||||
|
||||
/**
|
||||
- returns: `Observable` interface.
|
||||
*/
|
||||
public func asObservable() -> Observable<E> {
|
||||
return self.source
|
||||
}
|
||||
|
||||
/**
|
||||
- returns: `ControlEvent` interface.
|
||||
*/
|
||||
public func asControlEvent() -> ControlEvent<E> {
|
||||
return self
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,14 @@ import Foundation
|
|||
import RxSwift
|
||||
#endif
|
||||
|
||||
/**
|
||||
Protocol that enables extension of `ControlProperty`.
|
||||
*/
|
||||
public protocol ControlPropertyType : ObservableType, ObserverType {
|
||||
|
||||
/**
|
||||
- returns: `ControlProperty` interface
|
||||
*/
|
||||
func asControlProperty() -> ControlProperty<E>
|
||||
}
|
||||
|
||||
|
|
@ -38,18 +45,37 @@ public struct ControlProperty<PropertyType> : ControlPropertyType {
|
|||
self.observer = observer
|
||||
}
|
||||
|
||||
/**
|
||||
Subscribes an observer to control property values.
|
||||
|
||||
- parameter observer: Observer to subscribe to property values.
|
||||
- returns: Disposable object that can be used to unsubscribe the observer from receiving control property values.
|
||||
*/
|
||||
public func subscribe<O : ObserverType where O.E == E>(observer: O) -> Disposable {
|
||||
return self.source.subscribe(observer)
|
||||
}
|
||||
|
||||
/**
|
||||
- returns: `Observable` interface.
|
||||
*/
|
||||
public func asObservable() -> Observable<E> {
|
||||
return self.source
|
||||
}
|
||||
|
||||
/**
|
||||
- returns: `ControlProperty` interface.
|
||||
*/
|
||||
public func asControlProperty() -> ControlProperty<E> {
|
||||
return self
|
||||
}
|
||||
|
||||
/**
|
||||
Binds event to user interface.
|
||||
|
||||
- In case next element is received, it is being set to control value.
|
||||
- In case error is received, DEBUG buids raise fatal error, RELEASE builds log event to standard output.
|
||||
- In case sequence completes, nothing happens.
|
||||
*/
|
||||
public func on(event: Event<E>) {
|
||||
switch event {
|
||||
case .Error(let error):
|
||||
|
|
|
|||
|
|
@ -14,15 +14,22 @@ import RxSwift
|
|||
var delegateAssociatedTag: UInt8 = 0
|
||||
var dataSourceAssociatedTag: UInt8 = 0
|
||||
|
||||
// This should be only used from `MainScheduler`
|
||||
//
|
||||
// Also, please take a look at `DelegateProxyType` protocol implementation
|
||||
/**
|
||||
Base class for `DelegateProxyType` protocol.
|
||||
|
||||
This implementation is not thread safe and can be used only from one thread (Main thread).
|
||||
*/
|
||||
public class DelegateProxy : _RXDelegateProxy {
|
||||
|
||||
private var subjectsForSelector = [Selector: PublishSubject<[AnyObject]>]()
|
||||
|
||||
unowned let parentObject: AnyObject
|
||||
|
||||
/**
|
||||
Initializes new instance.
|
||||
|
||||
- parameter parentObject: Parent object that owns `DelegateProxy` as associated object.
|
||||
*/
|
||||
public required init(parentObject: AnyObject) {
|
||||
self.parentObject = parentObject
|
||||
|
||||
|
|
@ -33,6 +40,12 @@ public class DelegateProxy : _RXDelegateProxy {
|
|||
super.init()
|
||||
}
|
||||
|
||||
/**
|
||||
Returns observable sequence of invocations of delegate methods.
|
||||
|
||||
- parameter selector: Selector used to filter observed invocations of delegate methods.
|
||||
- returns: Observable sequence of arguments passed to `selector` method.
|
||||
*/
|
||||
public func observe(selector: Selector) -> Observable<[AnyObject]> {
|
||||
if hasWiredImplementationForSelector(selector) {
|
||||
print("Delegate proxy is already implementing `\(selector)`, a more performant way of registering might exist.")
|
||||
|
|
@ -64,29 +77,64 @@ public class DelegateProxy : _RXDelegateProxy {
|
|||
return p
|
||||
}
|
||||
|
||||
/**
|
||||
Returns tag used to identify associated object.
|
||||
|
||||
- returns: Associated object tag.
|
||||
*/
|
||||
public class func delegateAssociatedObjectTag() -> UnsafePointer<Void> {
|
||||
return _pointer(&delegateAssociatedTag)
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes new instance of delegate proxy.
|
||||
|
||||
- returns: Initialized instance of `self`.
|
||||
*/
|
||||
public class func createProxyForObject(object: AnyObject) -> AnyObject {
|
||||
return self.init(parentObject: object)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns assigned proxy for object.
|
||||
|
||||
- parameter object: Object that can have assigned delegate proxy.
|
||||
- returns: Assigned delegate proxy or `nil` if no delegate proxy is assigned.
|
||||
*/
|
||||
public class func assignedProxyFor(object: AnyObject) -> AnyObject? {
|
||||
let maybeDelegate: AnyObject? = objc_getAssociatedObject(object, self.delegateAssociatedObjectTag())
|
||||
return castOptionalOrFatalError(maybeDelegate)
|
||||
}
|
||||
|
||||
/**
|
||||
Assigns proxy to object.
|
||||
|
||||
- parameter object: Object that can have assigned delegate proxy.
|
||||
- parameter proxy: Delegate proxy object to assign to `object`.
|
||||
*/
|
||||
public class func assignProxy(proxy: AnyObject, toObject object: AnyObject) {
|
||||
precondition(proxy.isKindOfClass(self.classForCoder()))
|
||||
|
||||
objc_setAssociatedObject(object, self.delegateAssociatedObjectTag(), proxy, .OBJC_ASSOCIATION_RETAIN)
|
||||
}
|
||||
|
||||
/**
|
||||
Sets reference of normal delegate that receives all forwarded messages
|
||||
through `self`.
|
||||
|
||||
- parameter forwardToDelegate: Reference of delegate that receives all messages through `self`.
|
||||
- parameter retainDelegate: Should `self` retain `forwardToDelegate`.
|
||||
*/
|
||||
public func setForwardToDelegate(delegate: AnyObject?, retainDelegate: Bool) {
|
||||
self._setForwardToDelegate(delegate, retainDelegate: retainDelegate)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns reference of normal delegate that receives all forwarded messages
|
||||
through `self`.
|
||||
|
||||
- returns: Value of reference if set or nil.
|
||||
*/
|
||||
public func forwardToDelegate() -> AnyObject? {
|
||||
return self._forwardToDelegate
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,96 +11,161 @@ import Foundation
|
|||
import RxSwift
|
||||
#endif
|
||||
|
||||
// `DelegateProxyType` protocol enables using both normal delegates and Rx observables with
|
||||
// views that can have only one delegate/datasource registered.
|
||||
//
|
||||
// `Proxies` store information about observers, subscriptions and delegates
|
||||
// for specific views.
|
||||
//
|
||||
//
|
||||
// This is more or less how it works.
|
||||
//
|
||||
/*
|
||||
/**
|
||||
`DelegateProxyType` protocol enables using both normal delegates and Rx observable sequences with
|
||||
views that can have only one delegate/datasource registered.
|
||||
|
||||
`Proxies` store information about observers, subscriptions and delegates
|
||||
for specific views.
|
||||
|
||||
Type implementing `DelegateProxyType` should never be initialized directly.
|
||||
|
||||
To fetch initialized instance of type implementing `DelegateProxyType`, `proxyForObject` method
|
||||
should be used.
|
||||
|
||||
This is more or less how it works.
|
||||
|
||||
|
||||
|
||||
+-------------------------------------------+
|
||||
| |
|
||||
| UIView subclass (UIScrollView) |
|
||||
| |
|
||||
+-----------+-------------------------------+
|
||||
|
|
||||
| Delegate
|
||||
|
|
||||
|
|
||||
+-----------v-------------------------------+
|
||||
| |
|
||||
| Delegate proxy : DelegateProxyType +-----+----> Observable<T1>
|
||||
| , UIScrollViewDelegate | |
|
||||
+-----------+-------------------------------+ +----> Observable<T2>
|
||||
| |
|
||||
| +----> Observable<T3>
|
||||
| |
|
||||
| forwards events |
|
||||
| to custom delegate |
|
||||
| v
|
||||
+-----------v-------------------------------+
|
||||
| |
|
||||
| Custom delegate (UIScrollViewDelegate) |
|
||||
| |
|
||||
+-------------------------------------------+
|
||||
|
||||
|
||||
Since RxCocoa needs to automagically create those Proxys
|
||||
..and because views that have delegates can be hierarchical
|
||||
|
||||
UITableView : UIScrollView : UIView
|
||||
|
||||
.. and corresponding delegates are also hierarchical
|
||||
|
||||
UITableViewDelegate : UIScrollViewDelegate : NSObject
|
||||
|
||||
.. and sometimes there can be only one proxy/delegate registered,
|
||||
every view has a corresponding delegate virtual factory method.
|
||||
|
||||
In case of UITableView / UIScrollView, there is
|
||||
|
||||
extensions UIScrollView {
|
||||
public func rx_createDelegateProxy() -> RxScrollViewDelegateProxy {
|
||||
return RxScrollViewDelegateProxy(view: self)
|
||||
}
|
||||
....
|
||||
|
||||
|
||||
and override in UITableView
|
||||
|
||||
extension UITableView {
|
||||
public override func rx_createDelegateProxy() -> RxScrollViewDelegateProxy {
|
||||
....
|
||||
|
||||
+-------------------------------------------+
|
||||
| |
|
||||
| UIView subclass (UIScrollView) |
|
||||
| |
|
||||
+-----------+-------------------------------+
|
||||
|
|
||||
| Delegate
|
||||
|
|
||||
|
|
||||
+-----------v-------------------------------+
|
||||
| |
|
||||
| Delegate proxy : DelegateProxyType +-----+----> Observable<T1>
|
||||
| , UIScrollViewDelegate | |
|
||||
+-----------+-------------------------------+ +----> Observable<T2>
|
||||
| |
|
||||
| rx_bind(delegate) -> Disposable +----> Observable<T3>
|
||||
| |
|
||||
| proxies events |
|
||||
| |
|
||||
| v
|
||||
+-----------v-------------------------------+
|
||||
| |
|
||||
| Custom delegate (UIScrollViewDelegate) |
|
||||
| |
|
||||
+-------------------------------------------+
|
||||
|
||||
*/
|
||||
// Since RxCocoa needs to automagically create those Proxys
|
||||
// ..and because views that have delegates can be hierarchical
|
||||
//
|
||||
// UITableView : UIScrollView : UIView
|
||||
//
|
||||
// .. and corresponding delegates are also hierarchical
|
||||
//
|
||||
// UITableViewDelegate : UIScrollViewDelegate : NSObject
|
||||
//
|
||||
// .. and sometimes there can be only one proxy/delegate registered,
|
||||
// every view has a corresponding delegate virtual factory method.
|
||||
//
|
||||
// In case of UITableView / UIScrollView, there is
|
||||
//
|
||||
// ```
|
||||
// extensions UIScrollView {
|
||||
// public func rx_createDelegateProxy() -> RxScrollViewDelegateProxy {
|
||||
// return RxScrollViewDelegateProxy(view: self)
|
||||
// }
|
||||
//
|
||||
// ....
|
||||
// ```
|
||||
//
|
||||
// and override in UITableView
|
||||
//
|
||||
//```
|
||||
// extension UITableView {
|
||||
// public override func rx_createDelegateProxy() -> RxScrollViewDelegateProxy {
|
||||
// ....
|
||||
//```
|
||||
//
|
||||
public protocol DelegateProxyType : AnyObject {
|
||||
// Creates new proxy for target object.
|
||||
/**
|
||||
Creates new proxy for target object.
|
||||
*/
|
||||
static func createProxyForObject(object: AnyObject) -> AnyObject
|
||||
|
||||
// There can be only one registered proxy per object
|
||||
// These functions control that.
|
||||
/**
|
||||
Returns assigned proxy for object.
|
||||
|
||||
- parameter object: Object that can have assigned delegate proxy.
|
||||
- returns: Assigned delegate proxy or `nil` if no delegate proxy is assigned.
|
||||
*/
|
||||
static func assignedProxyFor(object: AnyObject) -> AnyObject?
|
||||
|
||||
/**
|
||||
Assigns proxy to object.
|
||||
|
||||
- parameter object: Object that can have assigned delegate proxy.
|
||||
- parameter proxy: Delegate proxy object to assign to `object`.
|
||||
*/
|
||||
static func assignProxy(proxy: AnyObject, toObject object: AnyObject)
|
||||
|
||||
// Set/Get current delegate for object
|
||||
/**
|
||||
Returns designated delegate property for object.
|
||||
|
||||
Objects can have mutltiple delegate properties.
|
||||
|
||||
Each delegate property needs to have it's own type implementing `DelegateProxyType`.
|
||||
|
||||
- parameter object: Object that has delegate property.
|
||||
- returns: Value of delegate property.
|
||||
*/
|
||||
static func currentDelegateFor(object: AnyObject) -> AnyObject?
|
||||
|
||||
/**
|
||||
Sets designated delegate property for object.
|
||||
|
||||
Objects can have mutltiple delegate properties.
|
||||
|
||||
Each delegate property needs to have it's own type implementing `DelegateProxyType`.
|
||||
|
||||
- parameter toObject: Object that has delegate property.
|
||||
- parameter delegate: Delegate value.
|
||||
*/
|
||||
static func setCurrentDelegate(delegate: AnyObject?, toObject object: AnyObject)
|
||||
|
||||
// Set/Get current delegate on proxy
|
||||
/**
|
||||
Returns reference of normal delegate that receives all forwarded messages
|
||||
through `self`.
|
||||
|
||||
- returns: Value of reference if set or nil.
|
||||
*/
|
||||
func forwardToDelegate() -> AnyObject?
|
||||
|
||||
/**
|
||||
Sets reference of normal delegate that receives all forwarded messages
|
||||
through `self`.
|
||||
|
||||
- parameter forwardToDelegate: Reference of delegate that receives all messages through `self`.
|
||||
- parameter retainDelegate: Should `self` retain `forwardToDelegate`.
|
||||
*/
|
||||
func setForwardToDelegate(forwardToDelegate: AnyObject?, retainDelegate: Bool)
|
||||
}
|
||||
|
||||
// future extensions :)
|
||||
/**
|
||||
Returns existing proxy for object or installs new instance of delegate proxy.
|
||||
|
||||
// this will install proxy if needed
|
||||
- parameter object: Target object on which to install delegate proxy.
|
||||
- returns: Installed instance of delegate proxy.
|
||||
|
||||
|
||||
extension UISearchBar {
|
||||
|
||||
public var rx_delegate: DelegateProxy {
|
||||
return proxyForObject(self) as RxSearchBarDelegateProxy
|
||||
}
|
||||
|
||||
public var rx_searchText: ControlProperty<String> {
|
||||
let source: Observable<String> = self.rx_delegate.observe("searchBar:textDidChange:")
|
||||
...
|
||||
}
|
||||
}
|
||||
*/
|
||||
public func proxyForObject<P: DelegateProxyType>(object: AnyObject) -> P {
|
||||
MainScheduler.ensureExecutingOnScheduler()
|
||||
|
||||
|
|
|
|||
|
|
@ -8,10 +8,15 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
// read your own configuration
|
||||
/**
|
||||
Simple logging settings for RxCocoa library.
|
||||
*/
|
||||
public struct Logging {
|
||||
public typealias LogURLRequest = (NSURLRequest) -> Bool
|
||||
|
||||
/**
|
||||
Log URL requests to standard output in curl format.
|
||||
*/
|
||||
public static var URLRequests: LogURLRequest = { _ in
|
||||
#if DEBUG
|
||||
return true
|
||||
|
|
|
|||
|
|
@ -13,14 +13,40 @@ import RxSwift
|
|||
|
||||
extension ObservableType {
|
||||
|
||||
public func bindTo<O: ObserverType where O.E == E>(target: O) -> Disposable {
|
||||
return self.subscribe(target)
|
||||
/**
|
||||
Creates new subscription and sends elements to observer.
|
||||
|
||||
In this form it's equivalent to `subscribe` method, but it communicates intent better.
|
||||
|
||||
- parameter observer: Observer that receives events.
|
||||
- returns: Disposable object that can be used to unsubscribe the observer from the subject.
|
||||
*/
|
||||
public func bindTo<O: ObserverType where O.E == E>(observer: O) -> Disposable {
|
||||
return self.subscribe(observer)
|
||||
}
|
||||
|
||||
/**
|
||||
Subscribes to observable sequence using custom binder function.
|
||||
|
||||
- parameter binder: Function used to bind elements from `self`.
|
||||
- returns: Object representing subscription.
|
||||
*/
|
||||
public func bindTo<R>(binder: Self -> R) -> R {
|
||||
return binder(self)
|
||||
}
|
||||
|
||||
/**
|
||||
Subscribes to observable sequence using custom binder function and final parameter passed to binder function
|
||||
after `self` is passed.
|
||||
|
||||
public func bindTo<R1, R2>(binder: Self -> R1 -> R2, curriedArgument: R1) -> R2 {
|
||||
return binder(self)(curriedArgument)
|
||||
}
|
||||
|
||||
- parameter binder: Function used to bind elements from `self`.
|
||||
- parameter curriedArgument: Final argument passed to `binder` to finish binding process.
|
||||
- returns: Object representing subscription.
|
||||
*/
|
||||
public func bindTo<R1, R2>(binder: Self -> R1 -> R2, curriedArgument: R1) -> R2 {
|
||||
return binder(self)(curriedArgument)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,15 @@ import RxSwift
|
|||
#endif
|
||||
|
||||
extension NSNotificationCenter {
|
||||
public func rx_notification(name: String, object: AnyObject?) -> Observable<NSNotification> {
|
||||
return AnonymousObservable { observer in
|
||||
/**
|
||||
Transforms notifications posted to notification center to observable sequence of notifications.
|
||||
|
||||
- parameter name: Filter notifications by name.
|
||||
- parameter object: Optional object used to filter notifications.
|
||||
- returns: Observable sequence of posted notifications.
|
||||
*/
|
||||
public func rx_notification(name: String, object: AnyObject? = nil) -> Observable<NSNotification> {
|
||||
return create { observer in
|
||||
let nsObserver = self.addObserverForName(name, object: object, queue: nil) { notification in
|
||||
observer.on(.Next(notification))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,11 @@ let CGPointType = "{CGPoint=ff}"
|
|||
|
||||
// rx_observe + CoreGraphics
|
||||
extension NSObject {
|
||||
/**
|
||||
Specialization of generic `rx_observe` method.
|
||||
|
||||
For more information take a look at `rx_observe` method.
|
||||
*/
|
||||
public func rx_observe(keyPath: String, options: NSKeyValueObservingOptions = NSKeyValueObservingOptions.New.union(NSKeyValueObservingOptions.Initial), retainSelf: Bool = true) -> Observable<CGRect?> {
|
||||
return rx_observe(keyPath, options: options, retainSelf: retainSelf)
|
||||
.map { (value: NSValue?) in
|
||||
|
|
@ -41,6 +46,11 @@ extension NSObject {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Specialization of generic `rx_observe` method.
|
||||
|
||||
For more information take a look at `rx_observe` method.
|
||||
*/
|
||||
public func rx_observe(keyPath: String, options: NSKeyValueObservingOptions = NSKeyValueObservingOptions.New.union(NSKeyValueObservingOptions.Initial), retainSelf: Bool = true) -> Observable<CGSize?> {
|
||||
return rx_observe(keyPath, options: options, retainSelf: retainSelf)
|
||||
.map { (value: NSValue?) in
|
||||
|
|
@ -58,6 +68,11 @@ extension NSObject {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Specialization of generic `rx_observe` method.
|
||||
|
||||
For more information take a look at `rx_observe` method.
|
||||
*/
|
||||
public func rx_observe(keyPath: String, options: NSKeyValueObservingOptions = NSKeyValueObservingOptions.New.union(NSKeyValueObservingOptions.Initial), retainSelf: Bool = true) -> Observable<CGPoint?> {
|
||||
return rx_observe(keyPath, options: options, retainSelf: retainSelf)
|
||||
.map { (value: NSValue?) in
|
||||
|
|
@ -80,6 +95,12 @@ extension NSObject {
|
|||
|
||||
// rx_observeWeakly + CoreGraphics
|
||||
extension NSObject {
|
||||
|
||||
/**
|
||||
Specialization of generic `rx_observeWeakly` method.
|
||||
|
||||
For more information take a look at `rx_observeWeakly` method.
|
||||
*/
|
||||
public func rx_observeWeakly(keyPath: String, options: NSKeyValueObservingOptions = NSKeyValueObservingOptions.New.union(NSKeyValueObservingOptions.Initial)) -> Observable<CGRect?> {
|
||||
return rx_observeWeakly(keyPath, options: options)
|
||||
.map { (value: NSValue?) in
|
||||
|
|
@ -97,6 +118,11 @@ extension NSObject {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Specialization of generic `rx_observeWeakly` method.
|
||||
|
||||
For more information take a look at `rx_observeWeakly` method.
|
||||
*/
|
||||
public func rx_observeWeakly(keyPath: String, options: NSKeyValueObservingOptions = NSKeyValueObservingOptions.New.union(NSKeyValueObservingOptions.Initial)) -> Observable<CGSize?> {
|
||||
return rx_observeWeakly(keyPath, options: options)
|
||||
.map { (value: NSValue?) in
|
||||
|
|
@ -114,6 +140,11 @@ extension NSObject {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Specialization of generic `rx_observeWeakly` method.
|
||||
|
||||
For more information take a look at `rx_observeWeakly` method.
|
||||
*/
|
||||
public func rx_observeWeakly(keyPath: String, options: NSKeyValueObservingOptions = NSKeyValueObservingOptions.New.union(NSKeyValueObservingOptions.Initial)) -> Observable<CGPoint?> {
|
||||
return rx_observeWeakly(keyPath, options: options)
|
||||
.map { (value: NSValue?) in
|
||||
|
|
|
|||
|
|
@ -41,7 +41,23 @@ var deallocatedSubjectContext: UInt8 = 0
|
|||
// KVO
|
||||
extension NSObject {
|
||||
|
||||
// Observes values on `keyPath` starting from `self` with `options` and retainsSelf if `retainSelf` is set.
|
||||
/**
|
||||
Observes values on `keyPath` starting from `self` with `options` and retains `self` if `retainSelf` is set.
|
||||
|
||||
`rx_observe` is just a simple and performant wrapper around KVO mechanism.
|
||||
|
||||
* it can be used to observe paths starting from `self` or from ancestors in ownership graph (`retainSelf = false`)
|
||||
* it can be used to observe paths starting from descendants in ownership graph (`retainSelf = true`)
|
||||
* the paths have to consist only of `strong` properties, otherwise you are risking crashing the system by not unregistering KVO observer before dealloc.
|
||||
|
||||
If support for weak properties is needed or observing arbitrary or unknown relationships in the
|
||||
ownership tree, `rx_observeWeakly` is the preferred option.
|
||||
|
||||
- parameter keyPath: Key path of property names to observe.
|
||||
- parameter options: KVO mechanism notification options.
|
||||
- parameter retainSelf: Retains self during observation if set `true`.
|
||||
- returns: Observable sequence of objects on `keyPath`.
|
||||
*/
|
||||
public func rx_observe<Element>(keyPath: String, options: NSKeyValueObservingOptions = NSKeyValueObservingOptions.New.union(NSKeyValueObservingOptions.Initial), retainSelf: Bool = true) -> Observable<Element?> {
|
||||
return KVOObservable(object: self, keyPath: keyPath, options: options, retainTarget: retainSelf)
|
||||
}
|
||||
|
|
@ -52,8 +68,20 @@ extension NSObject {
|
|||
// KVO
|
||||
extension NSObject {
|
||||
|
||||
// Observes values on `keyPath` starting from `self` with `options`
|
||||
// Doesn't retain `self` and when `self` is deallocated, completes the sequence.
|
||||
/**
|
||||
Observes values on `keyPath` starting from `self` with `options` and doesn't retain `self`.
|
||||
|
||||
It can be used in all cases where `rx_observe` can be used and additionally
|
||||
|
||||
* because it won't retain observed target, it can be used to observe arbitrary object graph whose ownership relation is unknown
|
||||
* it can be used to observe `weak` properties
|
||||
|
||||
**Since it needs to intercept object deallocation process it needs to perform swizzling of `dealloc` method on observed object.**
|
||||
|
||||
- parameter keyPath: Key path of property names to observe.
|
||||
- parameter options: KVO mechanism notification options.
|
||||
- returns: Observable sequence of objects on `keyPath`.
|
||||
*/
|
||||
public func rx_observeWeakly<Element>(keyPath: String, options: NSKeyValueObservingOptions = NSKeyValueObservingOptions.New.union(NSKeyValueObservingOptions.Initial)) -> Observable<Element?> {
|
||||
return observeWeaklyKeyPathFor(self, keyPath: keyPath, options: options)
|
||||
.map { n in
|
||||
|
|
@ -65,7 +93,14 @@ extension NSObject {
|
|||
|
||||
// Dealloc
|
||||
extension NSObject {
|
||||
// Sends next element when object is deallocated and immediately completes sequence.
|
||||
|
||||
/**
|
||||
Observable sequence of object deallocated events.
|
||||
|
||||
After object is deallocated one `()` element will be produced and sequence will immediately complete.
|
||||
|
||||
- returns: Observable sequence of object deallocated events.
|
||||
*/
|
||||
public var rx_deallocated: Observable<Void> {
|
||||
return rx_synchronized {
|
||||
if let subject = objc_getAssociatedObject(self, &deallocatedSubjectContext) as? ReplaySubject<Void> {
|
||||
|
|
@ -85,10 +120,15 @@ extension NSObject {
|
|||
}
|
||||
|
||||
#if !DISABLE_SWIZZLING
|
||||
// Sends element when object `dealloc` message is sent to `self`.
|
||||
// Completes when `self` was deallocated.
|
||||
//
|
||||
// Has performance penalty, so prefer `rx_deallocated` when ever possible.
|
||||
|
||||
/**
|
||||
Observable sequence of object deallocating events.
|
||||
|
||||
When `dealloc` message is sent to `self` one `()` element will be produced and after object is deallocated sequence
|
||||
will immediately complete.
|
||||
|
||||
- returns: Observable sequence of object deallocating events.
|
||||
*/
|
||||
public var rx_deallocating: Observable<Void> {
|
||||
return rx_synchronized {
|
||||
if let subject = objc_getAssociatedObject(self, &deallocatingSubjectContext) as? ReplaySubject<Void> {
|
||||
|
|
|
|||
|
|
@ -62,6 +62,18 @@ func convertResponseToString(data: NSData!, _ response: NSURLResponse!, _ error:
|
|||
}
|
||||
|
||||
extension NSURLSession {
|
||||
/**
|
||||
Observable sequence of responses for URL request.
|
||||
|
||||
Performing of request starts after observer is subscribed and not after invoking this method.
|
||||
|
||||
**URL requests will be performed per subscribed observer.**
|
||||
|
||||
Any error during fetching of the response will cause observed sequence to terminate with error.
|
||||
|
||||
- parameter request: URL request.
|
||||
- returns: Observable sequence of URL responses.
|
||||
*/
|
||||
public func rx_response(request: NSURLRequest) -> Observable<(NSData!, NSURLResponse!)> {
|
||||
return create { observer in
|
||||
|
||||
|
|
@ -81,7 +93,7 @@ extension NSURLSession {
|
|||
}
|
||||
|
||||
if data == nil || response == nil {
|
||||
observer.on(.Error(error ?? UnknownError))
|
||||
observer.on(.Error(error ?? RxError.UnknownError))
|
||||
}
|
||||
else {
|
||||
observer.on(.Next(data as NSData!, response as NSURLResponse!))
|
||||
|
|
@ -99,30 +111,76 @@ extension NSURLSession {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Observable sequence of response data for URL request.
|
||||
|
||||
Performing of request starts after observer is subscribed and not after invoking this method.
|
||||
|
||||
**URL requests will be performed per subscribed observer.**
|
||||
|
||||
Any error during fetching of the response will cause observed sequence to terminate with error.
|
||||
|
||||
If response is not HTTP response with status code in the range of `200 ..< 300`, sequence
|
||||
will terminate with `(RxCocoaErrorDomain, RxCocoaError.NetworkError)`.
|
||||
|
||||
- parameter request: URL request.
|
||||
- returns: Observable sequence of response data.
|
||||
*/
|
||||
public func rx_data(request: NSURLRequest) -> Observable<NSData> {
|
||||
return rx_response(request).map { (data, response) -> NSData in
|
||||
if let response = response as? NSHTTPURLResponse {
|
||||
if 200 ..< 300 ~= response.statusCode {
|
||||
return data ?? NSData()
|
||||
}
|
||||
else {
|
||||
throw rxError(.NetworkError, message: "Server returned failure", userInfo: [RxCocoaErrorHTTPResponseKey: response])
|
||||
}
|
||||
guard let response = response as? NSHTTPURLResponse else {
|
||||
throw RxError.UnknownError
|
||||
}
|
||||
|
||||
if 200 ..< 300 ~= response.statusCode {
|
||||
return data ?? NSData()
|
||||
}
|
||||
else {
|
||||
rxFatalError("response = nil")
|
||||
|
||||
throw UnknownError
|
||||
throw rxError(.NetworkError, message: "Server returned failure", userInfo: [RxCocoaErrorHTTPResponseKey: response])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Observable sequence of response JSON for URL request.
|
||||
|
||||
Performing of request starts after observer is subscribed and not after invoking this method.
|
||||
|
||||
**URL requests will be performed per subscribed observer.**
|
||||
|
||||
Any error during fetching of the response will cause observed sequence to terminate with error.
|
||||
|
||||
If response is not HTTP response with status code in the range of `200 ..< 300`, sequence
|
||||
will terminate with `(RxCocoaErrorDomain, RxCocoaError.NetworkError)`.
|
||||
|
||||
If there is an error during JSON deserialization observable sequence will fail with that error.
|
||||
|
||||
- parameter request: URL request.
|
||||
- returns: Observable sequence of response JSON.
|
||||
*/
|
||||
public func rx_JSON(request: NSURLRequest) -> Observable<AnyObject!> {
|
||||
return rx_data(request).map { (data) -> AnyObject! in
|
||||
return try NSJSONSerialization.JSONObjectWithData(data ?? NSData(), options: [])
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Observable sequence of response JSON for GET request with `URL`.
|
||||
|
||||
Performing of request starts after observer is subscribed and not after invoking this method.
|
||||
|
||||
**URL requests will be performed per subscribed observer.**
|
||||
|
||||
Any error during fetching of the response will cause observed sequence to terminate with error.
|
||||
|
||||
If response is not HTTP response with status code in the range of `200 ..< 300`, sequence
|
||||
will terminate with `(RxCocoaErrorDomain, RxCocoaError.NetworkError)`.
|
||||
|
||||
If there is an error during JSON deserialization observable sequence will fail with that error.
|
||||
|
||||
- parameter URL: URL of `NSURLRequest` request.
|
||||
- returns: Observable sequence of response JSON.
|
||||
*/
|
||||
public func rx_JSON(URL: NSURL) -> Observable<AnyObject!> {
|
||||
return rx_JSON(NSURLRequest(URL: URL))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,10 +21,14 @@ public enum RxCocoaError : Int {
|
|||
case KeyPathInvalid = 3
|
||||
}
|
||||
|
||||
let defaultHeight: CGFloat = -1
|
||||
|
||||
/**
|
||||
Error domain for internal RxCocoa errors.
|
||||
*/
|
||||
public let RxCocoaErrorDomain = "RxCocoaError"
|
||||
|
||||
/**
|
||||
`userInfo` key for `NSURLResponse` object when `RxCocoaError.NetworkError` happens.
|
||||
*/
|
||||
public let RxCocoaErrorHTTPResponseKey = "RxCocoaErrorHTTPResponseKey"
|
||||
|
||||
func rxError(errorCode: RxCocoaError, _ message: String) -> NSError {
|
||||
|
|
@ -46,10 +50,6 @@ func rxError(errorCode: RxCocoaError, message: String, userInfo: NSDictionary) -
|
|||
return NSError(domain: RxCocoaErrorDomain, code: Int(errorCode.rawValue), userInfo: resultInfo)
|
||||
}
|
||||
|
||||
func handleVoidObserverResult(result: RxResult<Void>) {
|
||||
handleObserverResult(result)
|
||||
}
|
||||
|
||||
func bindingErrorToInterface(error: ErrorType) {
|
||||
let error = "Binding error to UI: \(error)"
|
||||
#if DEBUG
|
||||
|
|
@ -67,15 +67,6 @@ func rxAbstractMethod<T>() -> T {
|
|||
return rxFatalErrorAndDontReturn("Abstract method")
|
||||
}
|
||||
|
||||
func handleObserverResult<T>(result: RxResult<T>) {
|
||||
switch result {
|
||||
case .Failure(let error):
|
||||
print("Error happened \(error)")
|
||||
rxFatalError("Error '\(error)' happened while ");
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
||||
// workaround for Swift compiler bug, cheers compiler team :)
|
||||
func castOptionalOrFatalError<T>(value: AnyObject?) -> T? {
|
||||
if value == nil {
|
||||
|
|
@ -86,23 +77,23 @@ func castOptionalOrFatalError<T>(value: AnyObject?) -> T? {
|
|||
}
|
||||
|
||||
func castOrFatalError<T>(value: AnyObject!, message: String) -> T {
|
||||
let result: RxResult<T> = castOrFail(value)
|
||||
|
||||
if result.isFailure {
|
||||
let maybeResult: T? = value as? T
|
||||
guard let result = maybeResult else {
|
||||
rxFatalError(message)
|
||||
return maybeResult!
|
||||
}
|
||||
|
||||
return result.get()
|
||||
return result
|
||||
}
|
||||
|
||||
func castOrFatalError<T>(value: AnyObject!) -> T {
|
||||
let result: RxResult<T> = castOrFail(value)
|
||||
|
||||
if result.isFailure {
|
||||
let maybeResult: T? = value as? T
|
||||
guard let result = maybeResult else {
|
||||
rxFatalError("Failure converting from \(value) to \(T.self)")
|
||||
return maybeResult!
|
||||
}
|
||||
|
||||
return result.get()
|
||||
return result
|
||||
}
|
||||
|
||||
// Error messages {
|
||||
|
|
@ -134,8 +125,4 @@ extension NSObject {
|
|||
}
|
||||
}
|
||||
|
||||
func removingObserverFailed() {
|
||||
rxFatalError("Removing observer for key failed")
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,62 +0,0 @@
|
|||
//
|
||||
// CoreDataEntityEvent.swift
|
||||
// RxCocoa
|
||||
//
|
||||
// Created by Krunoslav Zaher on 6/20/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
/*
|
||||
import Foundation
|
||||
import CoreData
|
||||
#if !RX_NO_MODULE
|
||||
import RxSwift
|
||||
#endif
|
||||
|
||||
enum CoreDataEntityEvent : CustomStringConvertible {
|
||||
|
||||
typealias SectionInfo = NSFetchedResultsSectionInfo
|
||||
|
||||
case Snapshot(sections: [SectionInfo])
|
||||
|
||||
case TransactionStarted
|
||||
case TransactionEnded
|
||||
|
||||
case ItemMoved(item: NSManagedObject, sourceIndexPath: NSIndexPath, destinationIndexPath: NSIndexPath)
|
||||
case ItemInserted(item: NSManagedObject, newIndexPath: NSIndexPath)
|
||||
case ItemDeleted(withIndexPath: NSIndexPath)
|
||||
case ItemUpdated(item: NSManagedObject, atIndexPath: NSIndexPath)
|
||||
|
||||
case SectionInserted(section: SectionInfo, newIndex: Int)
|
||||
case SectionDeleted(withIndex: Int)
|
||||
case SectionUpdated(section: SectionInfo, atIndex: Int)
|
||||
|
||||
|
||||
var description: String {
|
||||
get {
|
||||
switch self {
|
||||
case .Snapshot(sections: let snapshot):
|
||||
return "Snapshot(\(snapshot))"
|
||||
case TransactionStarted:
|
||||
return "TransactionStarted"
|
||||
case TransactionEnded:
|
||||
return "TransactionEnded"
|
||||
case ItemMoved(item: let item, sourceIndexPath: let sourceIndexPath, destinationIndexPath: let destinationIndexPath):
|
||||
return "ItemMoved(\(item), \(sourceIndexPath), \(destinationIndexPath))"
|
||||
case ItemInserted(item: let item, newIndexPath: let newIndexPath):
|
||||
return "ItemInserted(\(item), \(newIndexPath))"
|
||||
case ItemDeleted(withIndexPath: let indexPath):
|
||||
return "ItemDeleted(\(indexPath))"
|
||||
case ItemUpdated(item: let item, atIndexPath: let indexPath):
|
||||
return "ItemUpdated(\(item), \(indexPath))"
|
||||
case SectionInserted(section: let section, newIndex: let index):
|
||||
return "SectionInserted(\(section), \(index))"
|
||||
case SectionDeleted(withIndex: let index):
|
||||
return "SectionDeleted(\(index))"
|
||||
case SectionUpdated(section: let section, atIndex: let index):
|
||||
return "SectionUpdated(\(section), \(index))"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
@ -1,207 +0,0 @@
|
|||
//
|
||||
// NSManagedObjectContext+Rx.swift
|
||||
// RxCocoa
|
||||
//
|
||||
// Created by Krunoslav Zaher on 6/14/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
//import CoreData
|
||||
#if !RX_NO_MODULE
|
||||
import RxSwift
|
||||
#endif
|
||||
|
||||
/*
|
||||
class FetchResultControllerSectionObserver: NSObject, NSFetchedResultsControllerDelegate, Disposable {
|
||||
typealias Observer = ObserverOf<[NSFetchedResultsSectionInfo]>
|
||||
|
||||
let observer: Observer
|
||||
let frc: NSFetchedResultsController
|
||||
|
||||
init(observer: Observer, frc: NSFetchedResultsController) {
|
||||
self.observer = observer
|
||||
self.frc = frc
|
||||
|
||||
super.init()
|
||||
|
||||
self.frc.delegate = self
|
||||
|
||||
var error: NSError? = nil
|
||||
if !self.frc.performFetch(&error) {
|
||||
sendError(observer, error ?? UnknownError)
|
||||
return
|
||||
}
|
||||
|
||||
sendNextElement()
|
||||
}
|
||||
|
||||
func sendNextElement() {
|
||||
let sections = self.frc.sections as! [NSFetchedResultsSectionInfo]
|
||||
observer.on(.Next(sections))
|
||||
}
|
||||
|
||||
func controllerDidChangeContent(controller: NSFetchedResultsController) {
|
||||
sendNextElement()
|
||||
}
|
||||
|
||||
func dispose() {
|
||||
self.frc.delegate = nil
|
||||
}
|
||||
}
|
||||
|
||||
class FetchResultControllerEntityObserver: NSObject, NSFetchedResultsControllerDelegate, Disposable {
|
||||
typealias Observer = ObserverOf<[NSManagedObject]>
|
||||
|
||||
let observer: Observer
|
||||
let frc: NSFetchedResultsController
|
||||
|
||||
init(observer: Observer, frc: NSFetchedResultsController) {
|
||||
self.observer = observer
|
||||
self.frc = frc
|
||||
|
||||
super.init()
|
||||
|
||||
self.frc.delegate = self
|
||||
|
||||
var error: NSError? = nil
|
||||
if !self.frc.performFetch(&error) {
|
||||
sendError(observer, error ?? UnknownError)
|
||||
return
|
||||
}
|
||||
|
||||
sendNextElement()
|
||||
}
|
||||
|
||||
func sendNextElement() {
|
||||
let entities = self.frc.fetchedObjects as! [NSManagedObject]
|
||||
|
||||
observer.on(.Next(entities))
|
||||
}
|
||||
|
||||
func controllerDidChangeContent(controller: NSFetchedResultsController) {
|
||||
sendNextElement()
|
||||
}
|
||||
|
||||
func dispose() {
|
||||
self.frc.delegate = nil
|
||||
}
|
||||
}
|
||||
|
||||
class FetchResultControllerIncrementalObserver: NSObject, NSFetchedResultsControllerDelegate, Disposable {
|
||||
typealias Observer = ObserverOf<CoreDataEntityEvent>
|
||||
|
||||
let observer: Observer
|
||||
let frc: NSFetchedResultsController
|
||||
|
||||
init(observer: Observer, frc: NSFetchedResultsController) {
|
||||
self.observer = observer
|
||||
self.frc = frc
|
||||
|
||||
super.init()
|
||||
|
||||
self.frc.delegate = self
|
||||
|
||||
var error: NSError? = nil
|
||||
if !self.frc.performFetch(&error) {
|
||||
sendError(observer, error ?? UnknownError)
|
||||
return
|
||||
}
|
||||
|
||||
let sections = self.frc.sections as! [NSFetchedResultsSectionInfo]
|
||||
|
||||
observer.on(.Next(.Snapshot(sections: sections)))
|
||||
}
|
||||
|
||||
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
|
||||
|
||||
let event: CoreDataEntityEvent
|
||||
|
||||
switch type {
|
||||
case .Insert:
|
||||
event = .ItemInserted(item: anObject as! NSManagedObject, newIndexPath: newIndexPath!)
|
||||
case .Delete:
|
||||
event = .ItemDeleted(withIndexPath: indexPath!)
|
||||
case .Move:
|
||||
event = .ItemMoved(item: anObject as! NSManagedObject, sourceIndexPath: indexPath!, destinationIndexPath: newIndexPath!)
|
||||
case .Update:
|
||||
event = .ItemUpdated(item: anObject as! NSManagedObject, atIndexPath: indexPath!)
|
||||
}
|
||||
|
||||
observer.on(.Next(event))
|
||||
}
|
||||
|
||||
func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
|
||||
|
||||
let event: CoreDataEntityEvent
|
||||
|
||||
switch type {
|
||||
case .Insert:
|
||||
event = .SectionInserted(section: sectionInfo, newIndex: sectionIndex)
|
||||
case .Delete:
|
||||
event = .SectionDeleted(withIndex: sectionIndex)
|
||||
case .Move:
|
||||
rxFatalError("Unknown event")
|
||||
event = .SectionInserted(section: sectionInfo, newIndex: -1)
|
||||
case .Update:
|
||||
event = .SectionUpdated(section: sectionInfo, atIndex: sectionIndex)
|
||||
}
|
||||
|
||||
observer.on(.Next(event))
|
||||
}
|
||||
|
||||
func controllerWillChangeContent(controller: NSFetchedResultsController) {
|
||||
observer.on(.Next(.TransactionStarted))
|
||||
}
|
||||
|
||||
func controllerDidChangeContent(controller: NSFetchedResultsController) {
|
||||
observer.on(.Next(.TransactionEnded))
|
||||
}
|
||||
|
||||
func dispose() {
|
||||
self.frc.delegate = nil
|
||||
}
|
||||
}
|
||||
|
||||
extension NSManagedObjectContext {
|
||||
|
||||
func rx_entitiesAndChanges(query: NSFetchRequest) -> Observable<CoreDataEntityEvent> {
|
||||
return rx_sectionsAndChanges(query, sectionNameKeyPath: nil)
|
||||
}
|
||||
|
||||
func rx_sectionsAndChanges(query: NSFetchRequest, sectionNameKeyPath: String? = nil) -> Observable<CoreDataEntityEvent> {
|
||||
return AnonymousObservable { observer in
|
||||
let frc = NSFetchedResultsController(fetchRequest: query, managedObjectContext: self, sectionNameKeyPath: sectionNameKeyPath, cacheName: nil)
|
||||
|
||||
let observerAdapter = FetchResultControllerIncrementalObserver(observer: observer, frc: frc)
|
||||
|
||||
return AnonymousDisposable {
|
||||
observerAdapter.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func rx_entities(query: NSFetchRequest) -> Observable<[NSManagedObject]> {
|
||||
return AnonymousObservable { observer in
|
||||
let frc = NSFetchedResultsController(fetchRequest: query, managedObjectContext: self, sectionNameKeyPath: nil, cacheName: nil)
|
||||
|
||||
let observerAdapter = FetchResultControllerEntityObserver(observer: observer, frc: frc)
|
||||
|
||||
return AnonymousDisposable {
|
||||
observerAdapter.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func rx_sections(query: NSFetchRequest, sectionNameKeyPath: String) -> Observable<[NSFetchedResultsSectionInfo]> {
|
||||
return AnonymousObservable { observer in
|
||||
let frc = NSFetchedResultsController(fetchRequest: query, managedObjectContext: self, sectionNameKeyPath: sectionNameKeyPath, cacheName: nil)
|
||||
|
||||
let observerAdapter = FetchResultControllerSectionObserver(observer: observer, frc: frc)
|
||||
|
||||
return AnonymousDisposable {
|
||||
observerAdapter.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
|
@ -12,7 +12,9 @@ import UIKit
|
|||
import RxSwift
|
||||
#endif
|
||||
|
||||
// Please take a look at `DelegateProxyType.swift`
|
||||
/**
|
||||
Reactive data source for collection view.
|
||||
*/
|
||||
public protocol RxCollectionViewDataSourceType /*: UICollectionViewDataSource*/ {
|
||||
typealias Element
|
||||
|
||||
|
|
|
|||
|
|
@ -87,12 +87,13 @@ public class RxCollectionViewSectionedDataSource<S: SectionModelType> : _RxColle
|
|||
public var supplementaryViewFactory: SupplementaryViewFactory
|
||||
|
||||
public override init() {
|
||||
self.cellFactory = { _, _, _ in castOrFail(nil).get() }
|
||||
self.supplementaryViewFactory = { _, _, _ in castOrFail(nil).get() }
|
||||
self.cellFactory = { _, _, _ in return (nil as UICollectionViewCell?)! }
|
||||
self.supplementaryViewFactory = { _, _, _ in (nil as UICollectionReusableView?)! }
|
||||
|
||||
super.init()
|
||||
|
||||
self.cellFactory = { [weak self] _ in
|
||||
precondition(false, "There is a minor problem. `cellFactory` property on \(self!) was not set. Please set it manually, or use one of the `rx_subscribeTo` methods.")
|
||||
precondition(false, "There is a minor problem. `cellFactory` property on \(self!) was not set. Please set it manually, or use one of the `rx_bindTo` methods.")
|
||||
|
||||
return (nil as UICollectionViewCell!)!
|
||||
}
|
||||
|
|
@ -106,7 +107,7 @@ public class RxCollectionViewSectionedDataSource<S: SectionModelType> : _RxColle
|
|||
// observers
|
||||
|
||||
public func addIncrementalUpdatesObserver(observer: IncrementalUpdateObserver) -> IncrementalUpdateDisposeKey {
|
||||
return incrementalUpdateObservers.put(observer)
|
||||
return incrementalUpdateObservers.insert(observer)
|
||||
}
|
||||
|
||||
public func removeIncrementalUpdatesObserver(key: IncrementalUpdateDisposeKey) {
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ public class RxTableViewSectionedDataSource<S: SectionModelType> : _RxTableViewS
|
|||
super.init()
|
||||
self.cellFactory = { [weak self] _ in
|
||||
if let strongSelf = self {
|
||||
precondition(false, "There is a minor problem. `cellFactory` property on \(strongSelf) was not set. Please set it manually, or use one of the `rx_subscribeTo` methods.")
|
||||
precondition(false, "There is a minor problem. `cellFactory` property on \(strongSelf) was not set. Please set it manually, or use one of the `rx_bindTo` methods.")
|
||||
}
|
||||
|
||||
return (nil as UITableViewCell!)!
|
||||
|
|
@ -113,7 +113,7 @@ public class RxTableViewSectionedDataSource<S: SectionModelType> : _RxTableViewS
|
|||
// observers
|
||||
|
||||
public func addIncrementalUpdatesObserver(observer: IncrementalUpdateObserver) -> IncrementalUpdateDisposeKey {
|
||||
return incrementalUpdateObservers.put(observer)
|
||||
return incrementalUpdateObservers.insert(observer)
|
||||
}
|
||||
|
||||
public func removeIncrementalUpdatesObserver(key: IncrementalUpdateDisposeKey) {
|
||||
|
|
|
|||
|
|
@ -113,7 +113,6 @@
|
|||
C8A468F21B8A8C2600BF917B /* RxCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C8A468ED1B8A8BCC00BF917B /* RxCocoa.framework */; };
|
||||
C8A468F31B8A8C2600BF917B /* RxSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C8A468EB1B8A8BC900BF917B /* RxSwift.framework */; };
|
||||
C8A57F741B40AF7C00D5570A /* Random.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = C8A57F721B40AF7C00D5570A /* Random.xcdatamodeld */; };
|
||||
C8A74F1B1B94E5F400D8D046 /* AnyObject+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74E9F1B94E5F400D8D046 /* AnyObject+Rx.swift */; };
|
||||
C8A74F1C1B94E5F400D8D046 /* Cancelable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74EA01B94E5F400D8D046 /* Cancelable.swift */; };
|
||||
C8A74F1D1B94E5F400D8D046 /* AsyncLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74EA21B94E5F400D8D046 /* AsyncLock.swift */; };
|
||||
C8A74F1E1B94E5F400D8D046 /* Lock.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74EA31B94E5F400D8D046 /* Lock.swift */; };
|
||||
|
|
@ -124,7 +123,6 @@
|
|||
C8A74F231B94E5F400D8D046 /* Disposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74EA91B94E5F400D8D046 /* Disposable.swift */; };
|
||||
C8A74F241B94E5F400D8D046 /* AnonymousDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74EAB1B94E5F400D8D046 /* AnonymousDisposable.swift */; };
|
||||
C8A74F251B94E5F400D8D046 /* BinaryDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74EAC1B94E5F400D8D046 /* BinaryDisposable.swift */; };
|
||||
C8A74F261B94E5F400D8D046 /* BooleanDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74EAD1B94E5F400D8D046 /* BooleanDisposable.swift */; };
|
||||
C8A74F271B94E5F400D8D046 /* CompositeDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74EAE1B94E5F400D8D046 /* CompositeDisposable.swift */; };
|
||||
C8A74F281B94E5F400D8D046 /* DisposeBag.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74EAF1B94E5F400D8D046 /* DisposeBag.swift */; };
|
||||
C8A74F291B94E5F400D8D046 /* DisposeBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74EB01B94E5F400D8D046 /* DisposeBase.swift */; };
|
||||
|
|
@ -132,7 +130,7 @@
|
|||
C8A74F2B1B94E5F400D8D046 /* NAryDisposable.tt in Resources */ = {isa = PBXBuildFile; fileRef = C8A74EB21B94E5F400D8D046 /* NAryDisposable.tt */; };
|
||||
C8A74F2C1B94E5F400D8D046 /* NopDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74EB31B94E5F400D8D046 /* NopDisposable.swift */; };
|
||||
C8A74F2D1B94E5F400D8D046 /* ScheduledDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74EB41B94E5F400D8D046 /* ScheduledDisposable.swift */; };
|
||||
C8A74F2E1B94E5F400D8D046 /* ScopedDispose.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74EB51B94E5F400D8D046 /* ScopedDispose.swift */; };
|
||||
C8A74F2E1B94E5F400D8D046 /* ScopedDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74EB51B94E5F400D8D046 /* ScopedDisposable.swift */; };
|
||||
C8A74F2F1B94E5F400D8D046 /* SerialDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74EB61B94E5F400D8D046 /* SerialDisposable.swift */; };
|
||||
C8A74F301B94E5F400D8D046 /* SingleAssignmentDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74EB71B94E5F400D8D046 /* SingleAssignmentDisposable.swift */; };
|
||||
C8A74F311B94E5F400D8D046 /* StableCompositeDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74EB81B94E5F400D8D046 /* StableCompositeDisposable.swift */; };
|
||||
|
|
@ -169,7 +167,6 @@
|
|||
C8A74F501B94E5F400D8D046 /* Never.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74ED91B94E5F400D8D046 /* Never.swift */; };
|
||||
C8A74F511B94E5F400D8D046 /* ObserveOn.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74EDA1B94E5F400D8D046 /* ObserveOn.swift */; };
|
||||
C8A74F521B94E5F400D8D046 /* ObserveOnSerialDispatchQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74EDB1B94E5F400D8D046 /* ObserveOnSerialDispatchQueue.swift */; };
|
||||
C8A74F531B94E5F400D8D046 /* ObserveSingleOn.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74EDC1B94E5F400D8D046 /* ObserveSingleOn.swift */; };
|
||||
C8A74F541B94E5F400D8D046 /* Producer.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74EDD1B94E5F400D8D046 /* Producer.swift */; };
|
||||
C8A74F551B94E5F400D8D046 /* Reduce.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74EDE1B94E5F400D8D046 /* Reduce.swift */; };
|
||||
C8A74F561B94E5F400D8D046 /* RefCount.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74EDF1B94E5F400D8D046 /* RefCount.swift */; };
|
||||
|
|
@ -207,13 +204,11 @@
|
|||
C8A74F761B94E5F400D8D046 /* NopObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74F001B94E5F400D8D046 /* NopObserver.swift */; };
|
||||
C8A74F771B94E5F400D8D046 /* ObserverBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74F011B94E5F400D8D046 /* ObserverBase.swift */; };
|
||||
C8A74F781B94E5F400D8D046 /* SafeObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74F021B94E5F400D8D046 /* SafeObserver.swift */; };
|
||||
C8A74F791B94E5F400D8D046 /* ScheduledObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74F031B94E5F400D8D046 /* ScheduledObserver.swift */; };
|
||||
C8A74F7A1B94E5F400D8D046 /* TailRecursiveSink.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74F041B94E5F400D8D046 /* TailRecursiveSink.swift */; };
|
||||
C8A74F7B1B94E5F400D8D046 /* ObserverType+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74F051B94E5F400D8D046 /* ObserverType+Extensions.swift */; };
|
||||
C8A74F7C1B94E5F400D8D046 /* ObserverType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74F061B94E5F400D8D046 /* ObserverType.swift */; };
|
||||
C8A74F7D1B94E5F400D8D046 /* Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74F071B94E5F400D8D046 /* Rx.swift */; };
|
||||
C8A74F7E1B94E5F400D8D046 /* RxBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74F081B94E5F400D8D046 /* RxBox.swift */; };
|
||||
C8A74F7F1B94E5F400D8D046 /* RxResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74F091B94E5F400D8D046 /* RxResult.swift */; };
|
||||
C8A74F801B94E5F400D8D046 /* Scheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74F0A1B94E5F400D8D046 /* Scheduler.swift */; };
|
||||
C8A74F811B94E5F400D8D046 /* ConcurrentDispatchQueueScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74F0C1B94E5F400D8D046 /* ConcurrentDispatchQueueScheduler.swift */; };
|
||||
C8A74F821B94E5F400D8D046 /* CurrentThreadScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74F0D1B94E5F400D8D046 /* CurrentThreadScheduler.swift */; };
|
||||
|
|
@ -221,7 +216,6 @@
|
|||
C8A74F841B94E5F400D8D046 /* MainScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74F0F1B94E5F400D8D046 /* MainScheduler.swift */; };
|
||||
C8A74F851B94E5F400D8D046 /* OperationQueueScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74F101B94E5F400D8D046 /* OperationQueueScheduler.swift */; };
|
||||
C8A74F861B94E5F400D8D046 /* RecursiveScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74F111B94E5F400D8D046 /* RecursiveScheduler.swift */; };
|
||||
C8A74F871B94E5F400D8D046 /* Scheduler+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74F121B94E5F400D8D046 /* Scheduler+Extensions.swift */; };
|
||||
C8A74F881B94E5F400D8D046 /* SchedulerServices+Emulation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74F131B94E5F400D8D046 /* SchedulerServices+Emulation.swift */; };
|
||||
C8A74F891B94E5F400D8D046 /* SerialDispatchQueueScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74F141B94E5F400D8D046 /* SerialDispatchQueueScheduler.swift */; };
|
||||
C8A74F8A1B94E5F400D8D046 /* BehaviorSubject.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74F161B94E5F400D8D046 /* BehaviorSubject.swift */; };
|
||||
|
|
@ -253,11 +247,9 @@
|
|||
C8A74FF41B94E5FE00D8D046 /* RxCocoa.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74FAE1B94E5FE00D8D046 /* RxCocoa.swift */; };
|
||||
C8A74FF51B94E5FE00D8D046 /* RxTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74FAF1B94E5FE00D8D046 /* RxTarget.swift */; };
|
||||
C8A74FF61B94E5FE00D8D046 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = C8A74FB01B94E5FE00D8D046 /* Info.plist */; };
|
||||
C8A74FF71B94E5FE00D8D046 /* CoreDataEntityEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74FB21B94E5FE00D8D046 /* CoreDataEntityEvent.swift */; };
|
||||
C8A74FF81B94E5FE00D8D046 /* RxCollectionViewReactiveArrayDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74FB41B94E5FE00D8D046 /* RxCollectionViewReactiveArrayDataSource.swift */; };
|
||||
C8A74FF91B94E5FE00D8D046 /* RxTableViewReactiveArrayDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74FB51B94E5FE00D8D046 /* RxTableViewReactiveArrayDataSource.swift */; };
|
||||
C8A74FFA1B94E5FE00D8D046 /* ItemEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74FB71B94E5FE00D8D046 /* ItemEvents.swift */; };
|
||||
C8A74FFB1B94E5FE00D8D046 /* NSManagedObjectContext+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74FB81B94E5FE00D8D046 /* NSManagedObjectContext+Rx.swift */; };
|
||||
C8A74FFC1B94E5FE00D8D046 /* RxCollectionViewDataSourceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74FBA1B94E5FE00D8D046 /* RxCollectionViewDataSourceType.swift */; };
|
||||
C8A74FFD1B94E5FE00D8D046 /* RxTableViewDataSourceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74FBB1B94E5FE00D8D046 /* RxTableViewDataSourceType.swift */; };
|
||||
C8A74FFE1B94E5FE00D8D046 /* RxActionSheetDelegateProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A74FBD1B94E5FE00D8D046 /* RxActionSheetDelegateProxy.swift */; };
|
||||
|
|
@ -386,7 +378,6 @@
|
|||
C8A468ED1B8A8BCC00BF917B /* RxCocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = RxCocoa.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C8A468EF1B8A8BD000BF917B /* RxBlocking.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = RxBlocking.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C8A57F731B40AF7C00D5570A /* Random.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Random.xcdatamodel; sourceTree = "<group>"; };
|
||||
C8A74E9F1B94E5F400D8D046 /* AnyObject+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AnyObject+Rx.swift"; sourceTree = "<group>"; };
|
||||
C8A74EA01B94E5F400D8D046 /* Cancelable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cancelable.swift; sourceTree = "<group>"; };
|
||||
C8A74EA21B94E5F400D8D046 /* AsyncLock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsyncLock.swift; sourceTree = "<group>"; };
|
||||
C8A74EA31B94E5F400D8D046 /* Lock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Lock.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -397,7 +388,6 @@
|
|||
C8A74EA91B94E5F400D8D046 /* Disposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Disposable.swift; sourceTree = "<group>"; };
|
||||
C8A74EAB1B94E5F400D8D046 /* AnonymousDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnonymousDisposable.swift; sourceTree = "<group>"; };
|
||||
C8A74EAC1B94E5F400D8D046 /* BinaryDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BinaryDisposable.swift; sourceTree = "<group>"; };
|
||||
C8A74EAD1B94E5F400D8D046 /* BooleanDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BooleanDisposable.swift; sourceTree = "<group>"; };
|
||||
C8A74EAE1B94E5F400D8D046 /* CompositeDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompositeDisposable.swift; sourceTree = "<group>"; };
|
||||
C8A74EAF1B94E5F400D8D046 /* DisposeBag.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DisposeBag.swift; sourceTree = "<group>"; };
|
||||
C8A74EB01B94E5F400D8D046 /* DisposeBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DisposeBase.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -405,7 +395,7 @@
|
|||
C8A74EB21B94E5F400D8D046 /* NAryDisposable.tt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = NAryDisposable.tt; sourceTree = "<group>"; };
|
||||
C8A74EB31B94E5F400D8D046 /* NopDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NopDisposable.swift; sourceTree = "<group>"; };
|
||||
C8A74EB41B94E5F400D8D046 /* ScheduledDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScheduledDisposable.swift; sourceTree = "<group>"; };
|
||||
C8A74EB51B94E5F400D8D046 /* ScopedDispose.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScopedDispose.swift; sourceTree = "<group>"; };
|
||||
C8A74EB51B94E5F400D8D046 /* ScopedDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScopedDisposable.swift; sourceTree = "<group>"; };
|
||||
C8A74EB61B94E5F400D8D046 /* SerialDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SerialDisposable.swift; sourceTree = "<group>"; };
|
||||
C8A74EB71B94E5F400D8D046 /* SingleAssignmentDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleAssignmentDisposable.swift; sourceTree = "<group>"; };
|
||||
C8A74EB81B94E5F400D8D046 /* StableCompositeDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StableCompositeDisposable.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -442,7 +432,6 @@
|
|||
C8A74ED91B94E5F400D8D046 /* Never.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Never.swift; sourceTree = "<group>"; };
|
||||
C8A74EDA1B94E5F400D8D046 /* ObserveOn.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObserveOn.swift; sourceTree = "<group>"; };
|
||||
C8A74EDB1B94E5F400D8D046 /* ObserveOnSerialDispatchQueue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObserveOnSerialDispatchQueue.swift; sourceTree = "<group>"; };
|
||||
C8A74EDC1B94E5F400D8D046 /* ObserveSingleOn.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObserveSingleOn.swift; sourceTree = "<group>"; };
|
||||
C8A74EDD1B94E5F400D8D046 /* Producer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Producer.swift; sourceTree = "<group>"; };
|
||||
C8A74EDE1B94E5F400D8D046 /* Reduce.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Reduce.swift; sourceTree = "<group>"; };
|
||||
C8A74EDF1B94E5F400D8D046 /* RefCount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RefCount.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -480,13 +469,11 @@
|
|||
C8A74F001B94E5F400D8D046 /* NopObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NopObserver.swift; sourceTree = "<group>"; };
|
||||
C8A74F011B94E5F400D8D046 /* ObserverBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObserverBase.swift; sourceTree = "<group>"; };
|
||||
C8A74F021B94E5F400D8D046 /* SafeObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SafeObserver.swift; sourceTree = "<group>"; };
|
||||
C8A74F031B94E5F400D8D046 /* ScheduledObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScheduledObserver.swift; sourceTree = "<group>"; };
|
||||
C8A74F041B94E5F400D8D046 /* TailRecursiveSink.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TailRecursiveSink.swift; sourceTree = "<group>"; };
|
||||
C8A74F051B94E5F400D8D046 /* ObserverType+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ObserverType+Extensions.swift"; sourceTree = "<group>"; };
|
||||
C8A74F061B94E5F400D8D046 /* ObserverType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObserverType.swift; sourceTree = "<group>"; };
|
||||
C8A74F071B94E5F400D8D046 /* Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Rx.swift; sourceTree = "<group>"; };
|
||||
C8A74F081B94E5F400D8D046 /* RxBox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxBox.swift; sourceTree = "<group>"; };
|
||||
C8A74F091B94E5F400D8D046 /* RxResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxResult.swift; sourceTree = "<group>"; };
|
||||
C8A74F0A1B94E5F400D8D046 /* Scheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Scheduler.swift; sourceTree = "<group>"; };
|
||||
C8A74F0C1B94E5F400D8D046 /* ConcurrentDispatchQueueScheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConcurrentDispatchQueueScheduler.swift; sourceTree = "<group>"; };
|
||||
C8A74F0D1B94E5F400D8D046 /* CurrentThreadScheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CurrentThreadScheduler.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -494,7 +481,6 @@
|
|||
C8A74F0F1B94E5F400D8D046 /* MainScheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainScheduler.swift; sourceTree = "<group>"; };
|
||||
C8A74F101B94E5F400D8D046 /* OperationQueueScheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperationQueueScheduler.swift; sourceTree = "<group>"; };
|
||||
C8A74F111B94E5F400D8D046 /* RecursiveScheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecursiveScheduler.swift; sourceTree = "<group>"; };
|
||||
C8A74F121B94E5F400D8D046 /* Scheduler+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Scheduler+Extensions.swift"; sourceTree = "<group>"; };
|
||||
C8A74F131B94E5F400D8D046 /* SchedulerServices+Emulation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SchedulerServices+Emulation.swift"; sourceTree = "<group>"; };
|
||||
C8A74F141B94E5F400D8D046 /* SerialDispatchQueueScheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SerialDispatchQueueScheduler.swift; sourceTree = "<group>"; };
|
||||
C8A74F161B94E5F400D8D046 /* BehaviorSubject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BehaviorSubject.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -530,11 +516,9 @@
|
|||
C8A74FAE1B94E5FE00D8D046 /* RxCocoa.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxCocoa.swift; sourceTree = "<group>"; };
|
||||
C8A74FAF1B94E5FE00D8D046 /* RxTarget.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxTarget.swift; sourceTree = "<group>"; };
|
||||
C8A74FB01B94E5FE00D8D046 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
C8A74FB21B94E5FE00D8D046 /* CoreDataEntityEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataEntityEvent.swift; sourceTree = "<group>"; };
|
||||
C8A74FB41B94E5FE00D8D046 /* RxCollectionViewReactiveArrayDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxCollectionViewReactiveArrayDataSource.swift; sourceTree = "<group>"; };
|
||||
C8A74FB51B94E5FE00D8D046 /* RxTableViewReactiveArrayDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxTableViewReactiveArrayDataSource.swift; sourceTree = "<group>"; };
|
||||
C8A74FB71B94E5FE00D8D046 /* ItemEvents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ItemEvents.swift; sourceTree = "<group>"; };
|
||||
C8A74FB81B94E5FE00D8D046 /* NSManagedObjectContext+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectContext+Rx.swift"; sourceTree = "<group>"; };
|
||||
C8A74FBA1B94E5FE00D8D046 /* RxCollectionViewDataSourceType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxCollectionViewDataSourceType.swift; sourceTree = "<group>"; };
|
||||
C8A74FBB1B94E5FE00D8D046 /* RxTableViewDataSourceType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxTableViewDataSourceType.swift; sourceTree = "<group>"; };
|
||||
C8A74FBD1B94E5FE00D8D046 /* RxActionSheetDelegateProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxActionSheetDelegateProxy.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -859,7 +843,6 @@
|
|||
C8A74E9E1B94E5F400D8D046 /* RxSwift */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C8A74E9F1B94E5F400D8D046 /* AnyObject+Rx.swift */,
|
||||
C8A74EA01B94E5F400D8D046 /* Cancelable.swift */,
|
||||
C8A74EA11B94E5F400D8D046 /* Concurrency */,
|
||||
C8A74EA41B94E5F400D8D046 /* ConnectableObservableType.swift */,
|
||||
|
|
@ -881,7 +864,6 @@
|
|||
C8A74F061B94E5F400D8D046 /* ObserverType.swift */,
|
||||
C8A74F071B94E5F400D8D046 /* Rx.swift */,
|
||||
C8A74F081B94E5F400D8D046 /* RxBox.swift */,
|
||||
C8A74F091B94E5F400D8D046 /* RxResult.swift */,
|
||||
C8A74F0A1B94E5F400D8D046 /* Scheduler.swift */,
|
||||
C8A74F0B1B94E5F400D8D046 /* Schedulers */,
|
||||
C8A74F151B94E5F400D8D046 /* Subjects */,
|
||||
|
|
@ -914,7 +896,6 @@
|
|||
children = (
|
||||
C8A74EAB1B94E5F400D8D046 /* AnonymousDisposable.swift */,
|
||||
C8A74EAC1B94E5F400D8D046 /* BinaryDisposable.swift */,
|
||||
C8A74EAD1B94E5F400D8D046 /* BooleanDisposable.swift */,
|
||||
C8A74EAE1B94E5F400D8D046 /* CompositeDisposable.swift */,
|
||||
C8A74EAF1B94E5F400D8D046 /* DisposeBag.swift */,
|
||||
C8A74EB01B94E5F400D8D046 /* DisposeBase.swift */,
|
||||
|
|
@ -922,7 +903,7 @@
|
|||
C8A74EB21B94E5F400D8D046 /* NAryDisposable.tt */,
|
||||
C8A74EB31B94E5F400D8D046 /* NopDisposable.swift */,
|
||||
C8A74EB41B94E5F400D8D046 /* ScheduledDisposable.swift */,
|
||||
C8A74EB51B94E5F400D8D046 /* ScopedDispose.swift */,
|
||||
C8A74EB51B94E5F400D8D046 /* ScopedDisposable.swift */,
|
||||
C8A74EB61B94E5F400D8D046 /* SerialDisposable.swift */,
|
||||
C8A74EB71B94E5F400D8D046 /* SingleAssignmentDisposable.swift */,
|
||||
C8A74EB81B94E5F400D8D046 /* StableCompositeDisposable.swift */,
|
||||
|
|
@ -977,7 +958,6 @@
|
|||
C8A74ED91B94E5F400D8D046 /* Never.swift */,
|
||||
C8A74EDA1B94E5F400D8D046 /* ObserveOn.swift */,
|
||||
C8A74EDB1B94E5F400D8D046 /* ObserveOnSerialDispatchQueue.swift */,
|
||||
C8A74EDC1B94E5F400D8D046 /* ObserveSingleOn.swift */,
|
||||
C8A74EDD1B94E5F400D8D046 /* Producer.swift */,
|
||||
C8A74EDE1B94E5F400D8D046 /* Reduce.swift */,
|
||||
C8A74EDF1B94E5F400D8D046 /* RefCount.swift */,
|
||||
|
|
@ -1010,7 +990,6 @@
|
|||
C8A74F001B94E5F400D8D046 /* NopObserver.swift */,
|
||||
C8A74F011B94E5F400D8D046 /* ObserverBase.swift */,
|
||||
C8A74F021B94E5F400D8D046 /* SafeObserver.swift */,
|
||||
C8A74F031B94E5F400D8D046 /* ScheduledObserver.swift */,
|
||||
C8A74F041B94E5F400D8D046 /* TailRecursiveSink.swift */,
|
||||
);
|
||||
path = Observers;
|
||||
|
|
@ -1025,7 +1004,6 @@
|
|||
C8A74F0F1B94E5F400D8D046 /* MainScheduler.swift */,
|
||||
C8A74F101B94E5F400D8D046 /* OperationQueueScheduler.swift */,
|
||||
C8A74F111B94E5F400D8D046 /* RecursiveScheduler.swift */,
|
||||
C8A74F121B94E5F400D8D046 /* Scheduler+Extensions.swift */,
|
||||
C8A74F131B94E5F400D8D046 /* SchedulerServices+Emulation.swift */,
|
||||
C8A74F141B94E5F400D8D046 /* SerialDispatchQueueScheduler.swift */,
|
||||
);
|
||||
|
|
@ -1125,10 +1103,8 @@
|
|||
C8A74FB11B94E5FE00D8D046 /* iOS */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C8A74FB21B94E5FE00D8D046 /* CoreDataEntityEvent.swift */,
|
||||
C8A74FB31B94E5FE00D8D046 /* DataSources */,
|
||||
C8A74FB61B94E5FE00D8D046 /* Events */,
|
||||
C8A74FB81B94E5FE00D8D046 /* NSManagedObjectContext+Rx.swift */,
|
||||
C8A74FB91B94E5FE00D8D046 /* Protocols */,
|
||||
C8A74FBC1B94E5FE00D8D046 /* Proxies */,
|
||||
C8A74FC61B94E5FE00D8D046 /* UIActionSheet+Rx.swift */,
|
||||
|
|
@ -1375,7 +1351,6 @@
|
|||
C8A74F3B1B94E5F400D8D046 /* AsObservable.swift in Sources */,
|
||||
C8A750031B94E5FE00D8D046 /* RxSearchBarDelegateProxy.swift in Sources */,
|
||||
C8A74F4C1B94E5F400D8D046 /* Just.swift in Sources */,
|
||||
C8A74F7F1B94E5F400D8D046 /* RxResult.swift in Sources */,
|
||||
C8A750151B94E5FE00D8D046 /* UISwitch+Rx.swift in Sources */,
|
||||
C8297E301B6CF905000589EA /* RandomUserAPI.swift in Sources */,
|
||||
C8297E311B6CF905000589EA /* SearchResultViewModel.swift in Sources */,
|
||||
|
|
@ -1400,7 +1375,6 @@
|
|||
C8A74FED1B94E5FE00D8D046 /* KVOObservable.swift in Sources */,
|
||||
C8A74F671B94E5F400D8D046 /* Observable+Aggregate.swift in Sources */,
|
||||
C8A74F821B94E5F400D8D046 /* CurrentThreadScheduler.swift in Sources */,
|
||||
C8A74F531B94E5F400D8D046 /* ObserveSingleOn.swift in Sources */,
|
||||
C8A74F201B94E5F400D8D046 /* Bag.swift in Sources */,
|
||||
C8A74F4E1B94E5F400D8D046 /* Merge.swift in Sources */,
|
||||
C8A74F621B94E5F400D8D046 /* Timer.swift in Sources */,
|
||||
|
|
@ -1427,7 +1401,6 @@
|
|||
C8A74F761B94E5F400D8D046 /* NopObserver.swift in Sources */,
|
||||
C8A74F371B94E5F400D8D046 /* Observable+Extensions.swift in Sources */,
|
||||
C8A74F6A1B94E5F400D8D046 /* Observable+Creation.swift in Sources */,
|
||||
C8A74F261B94E5F400D8D046 /* BooleanDisposable.swift in Sources */,
|
||||
C8A74F661B94E5F400D8D046 /* Zip.swift in Sources */,
|
||||
C8A74F281B94E5F400D8D046 /* DisposeBag.swift in Sources */,
|
||||
C8A750101B94E5FE00D8D046 /* UILabel+Rx.swift in Sources */,
|
||||
|
|
@ -1438,12 +1411,10 @@
|
|||
C8A74FEA1B94E5FE00D8D046 /* ControlTarget.swift in Sources */,
|
||||
C8A74F631B94E5F400D8D046 /* Zip+arity.swift in Sources */,
|
||||
C8297E3A1B6CF905000589EA /* WikipediaSearchViewController.swift in Sources */,
|
||||
C8A74FF71B94E5FE00D8D046 /* CoreDataEntityEvent.swift in Sources */,
|
||||
C8297E3B1B6CF905000589EA /* String+extensions.swift in Sources */,
|
||||
C8297E3C1B6CF905000589EA /* SectionModel.swift in Sources */,
|
||||
C8A74F771B94E5F400D8D046 /* ObserverBase.swift in Sources */,
|
||||
C8297E3D1B6CF905000589EA /* SearchViewModel.swift in Sources */,
|
||||
C8A74FFB1B94E5FE00D8D046 /* NSManagedObjectContext+Rx.swift in Sources */,
|
||||
C8A74F321B94E5F400D8D046 /* TernaryDisposable.swift in Sources */,
|
||||
C8A74F6B1B94E5F400D8D046 /* Observable+Debug.swift in Sources */,
|
||||
C8A74F7E1B94E5F400D8D046 /* RxBox.swift in Sources */,
|
||||
|
|
@ -1489,7 +1460,6 @@
|
|||
C8A7500E1B94E5FE00D8D046 /* UIGestureRecognizer+Rx.swift in Sources */,
|
||||
C8A74F831B94E5F400D8D046 /* DispatchQueueSchedulerPriority.swift in Sources */,
|
||||
C8A74F801B94E5F400D8D046 /* Scheduler.swift in Sources */,
|
||||
C8A74F871B94E5F400D8D046 /* Scheduler+Extensions.swift in Sources */,
|
||||
C8A74F681B94E5F400D8D046 /* Observable+Binding.swift in Sources */,
|
||||
C8297E471B6CF905000589EA /* ViewController.swift in Sources */,
|
||||
C8297E481B6CF905000589EA /* Differentiator.swift in Sources */,
|
||||
|
|
@ -1503,9 +1473,7 @@
|
|||
C8A74F851B94E5F400D8D046 /* OperationQueueScheduler.swift in Sources */,
|
||||
C8297E4A1B6CF905000589EA /* GitHubSignupViewController.swift in Sources */,
|
||||
C8A74F231B94E5F400D8D046 /* Disposable.swift in Sources */,
|
||||
C8A74F1B1B94E5F400D8D046 /* AnyObject+Rx.swift in Sources */,
|
||||
C8A74FE91B94E5FE00D8D046 /* Observable+CocoaExtensions.swift in Sources */,
|
||||
C8A74F791B94E5F400D8D046 /* ScheduledObserver.swift in Sources */,
|
||||
C8A750161B94E5FE00D8D046 /* UITableView+Rx.swift in Sources */,
|
||||
C8297E4B1B6CF905000589EA /* Random.xcdatamodeld in Sources */,
|
||||
C8A750021B94E5FE00D8D046 /* RxScrollViewDelegateProxy.swift in Sources */,
|
||||
|
|
@ -1535,7 +1503,7 @@
|
|||
C8A74FEE1B94E5FE00D8D046 /* KVOObserver.swift in Sources */,
|
||||
C8A74FFC1B94E5FE00D8D046 /* RxCollectionViewDataSourceType.swift in Sources */,
|
||||
C8A750121B94E5FE00D8D046 /* UISearchBar+Rx.swift in Sources */,
|
||||
C8A74F2E1B94E5F400D8D046 /* ScopedDispose.swift in Sources */,
|
||||
C8A74F2E1B94E5F400D8D046 /* ScopedDisposable.swift in Sources */,
|
||||
C8A74F841B94E5F400D8D046 /* MainScheduler.swift in Sources */,
|
||||
C8297E521B6CF905000589EA /* Dependencies.swift in Sources */,
|
||||
C8A74F881B94E5F400D8D046 /* SchedulerServices+Emulation.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -97,7 +97,8 @@ class CalculatorViewController: ViewController {
|
|||
nineButton.rx_tap.map { _ in .AddNumber("9") }
|
||||
]
|
||||
|
||||
from(commands)
|
||||
commands
|
||||
.asObservable()
|
||||
.merge()
|
||||
.scan(CLEAR_STATE) { [unowned self] a, x in
|
||||
return self.tranformState(a, x)
|
||||
|
|
|
|||
|
|
@ -54,8 +54,8 @@ class GitHubAPI {
|
|||
return false
|
||||
}
|
||||
}
|
||||
.observeSingleOn(self.dataScheduler)
|
||||
.catchErrorResumeNext(false)
|
||||
.observeOn(self.dataScheduler)
|
||||
.catchErrorJustReturn(false)
|
||||
}
|
||||
|
||||
func signup(username: String, password: String) -> Observable<SignupState> {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,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!
|
||||
|
|
@ -109,7 +109,7 @@ class PartialUpdatesViewController : ViewController {
|
|||
timer = NSTimer.scheduledTimerWithTimeInterval(0.6, target: self, selector: "randomize", userInfo: nil, repeats: true)
|
||||
#endif
|
||||
|
||||
self.sections.sendNext(generator.sections)
|
||||
self.sections.value = generator.sections
|
||||
|
||||
let tvAnimatedDataSource = RxTableViewSectionedAnimatedDataSource<NumberSection>()
|
||||
let reloadDataSource = RxTableViewSectionedReloadDataSource<NumberSection>()
|
||||
|
|
@ -147,7 +147,7 @@ class PartialUpdatesViewController : ViewController {
|
|||
// While `useAnimatedUpdateForCollectionView` is false, you can click as fast as
|
||||
// you want, table view doesn't seem to have same issues like collection view.
|
||||
|
||||
#if useAnimatedUpdateForCollectionView
|
||||
#if useAnimatedUpdateForCollectionView
|
||||
let cvAnimatedDataSource = RxCollectionViewSectionedAnimatedDataSource<NumberSection>()
|
||||
skinCollectionViewDataSource(cvAnimatedDataSource)
|
||||
|
||||
|
|
@ -193,6 +193,6 @@ class PartialUpdatesViewController : ViewController {
|
|||
|
||||
//print(values)
|
||||
|
||||
sections.sendNext(values)
|
||||
sections.value = values
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class DetailViewController: ViewController {
|
|||
.map { data in
|
||||
UIImage(data: data)
|
||||
}
|
||||
.observeSingleOn($.mainScheduler)
|
||||
.observeOn($.mainScheduler)
|
||||
.subscribe(imageView.rx_image)
|
||||
.addDisposableTo(disposeBag)
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class RandomUserAPI {
|
|||
func getExampleUserResultSet() -> Observable<[User]> {
|
||||
let url = NSURL(string: "http://api.randomuser.me/?results=20")!
|
||||
return NSURLSession.sharedSession().rx_JSON(url)
|
||||
.observeSingleOn(Dependencies.sharedDependencies.backgroundWorkScheduler)
|
||||
.observeOn(Dependencies.sharedDependencies.backgroundWorkScheduler)
|
||||
.map { json in
|
||||
guard let json = json as? [String: AnyObject] else {
|
||||
throw exampleError("Casting to dictionary failed")
|
||||
|
|
@ -28,7 +28,7 @@ class RandomUserAPI {
|
|||
|
||||
return try self.parseJSON(json)
|
||||
}
|
||||
.observeSingleOn(Dependencies.sharedDependencies.mainScheduler)
|
||||
.observeOn(Dependencies.sharedDependencies.mainScheduler)
|
||||
}
|
||||
|
||||
private func parseJSON(json: [String: AnyObject]) throws -> [User] {
|
||||
|
|
@ -39,22 +39,21 @@ class RandomUserAPI {
|
|||
let users = results.map { $0["user"] as? [String: AnyObject] }.filter { $0 != nil }
|
||||
|
||||
let userParsingError = exampleError("Can't parse user")
|
||||
|
||||
let searchResults: [RxResult<User>] = users.map { user in
|
||||
|
||||
let searchResults: [User] = try users.map { user in
|
||||
let name = user?["name"] as? [String: String]
|
||||
let pictures = user?["picture"] as? [String: String]
|
||||
|
||||
guard let firstName = name?["first"], let lastName = name?["last"], let imageURL = pictures?["medium"] else {
|
||||
return failure(userParsingError)
|
||||
throw userParsingError
|
||||
}
|
||||
|
||||
let returnUser = User(firstName: firstName.capitalizedString,
|
||||
lastName: lastName.capitalizedString,
|
||||
imageURL: imageURL)
|
||||
return success(returnUser)
|
||||
return returnUser
|
||||
}
|
||||
|
||||
let values = (searchResults.filter { $0.isSuccess }).map { $0.get() }
|
||||
return values
|
||||
return searchResults
|
||||
}
|
||||
}
|
||||
|
|
@ -13,33 +13,33 @@ import RxCocoa
|
|||
#endif
|
||||
|
||||
class TableViewController: ViewController, UITableViewDelegate {
|
||||
|
||||
|
||||
|
||||
|
||||
@IBOutlet weak var tableView: UITableView!
|
||||
|
||||
|
||||
var disposeBag = DisposeBag()
|
||||
|
||||
|
||||
let users = Variable([User]())
|
||||
let favoriteUsers = Variable([User]())
|
||||
|
||||
|
||||
var allSections: [SectionModel<String, User>] = []
|
||||
|
||||
|
||||
let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, User>>()
|
||||
|
||||
typealias Section = SectionModel<String, User>
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
|
||||
self.navigationItem.rightBarButtonItem = self.editButtonItem()
|
||||
|
||||
|
||||
let allUsers = combineLatest(favoriteUsers, users) { favoriteUsers, users in
|
||||
return [
|
||||
SectionModel(model: "Favorite Users", items: favoriteUsers),
|
||||
SectionModel(model: "Normal Users", items: users)
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
// This is for demonstration purposes of UITableViewDelegate/DataSource
|
||||
// only, try to not do something like this in your app
|
||||
allUsers
|
||||
|
|
@ -47,80 +47,86 @@ class TableViewController: ViewController, UITableViewDelegate {
|
|||
self.allSections = n
|
||||
}
|
||||
.addDisposableTo(disposeBag)
|
||||
|
||||
|
||||
dataSource.cellFactory = { (tv, ip, user: User) in
|
||||
let cell = tv.dequeueReusableCellWithIdentifier("Cell")!
|
||||
cell.textLabel?.text = user.firstName + " " + user.lastName
|
||||
return cell
|
||||
}
|
||||
|
||||
|
||||
dataSource.titleForHeaderInSection = { [unowned dataSource] sectionIndex in
|
||||
return dataSource.sectionAtIndex(sectionIndex).model
|
||||
}
|
||||
|
||||
|
||||
// reactive data source
|
||||
allUsers
|
||||
.bindTo(tableView.rx_itemsWithDataSource(dataSource))
|
||||
.addDisposableTo(disposeBag)
|
||||
|
||||
|
||||
// customization using delegate
|
||||
// RxTableViewDelegateBridge will forward correct messages
|
||||
tableView.rx_setDelegate(self)
|
||||
.addDisposableTo(disposeBag)
|
||||
|
||||
|
||||
tableView.rx_itemSelected
|
||||
.subscribeNext { [unowned self] indexPath in
|
||||
self.showDetailsForUserAtIndexPath(indexPath)
|
||||
}
|
||||
.addDisposableTo(disposeBag)
|
||||
|
||||
|
||||
tableView.rx_itemDeleted
|
||||
.subscribeNext { [unowned self] indexPath in
|
||||
self.removeUser(indexPath)
|
||||
}
|
||||
.addDisposableTo(disposeBag)
|
||||
|
||||
|
||||
tableView.rx_itemMoved
|
||||
.subscribeNext { [unowned self] (s, d) in
|
||||
self.moveUserFrom(s, to: d)
|
||||
}
|
||||
.addDisposableTo(disposeBag)
|
||||
|
||||
|
||||
// Rx content offset
|
||||
tableView.rx_contentOffset
|
||||
.subscribeNext { co in
|
||||
print("Content offset from Rx observer \(co)")
|
||||
}
|
||||
|
||||
|
||||
RandomUserAPI.sharedAPI.getExampleUserResultSet()
|
||||
.subscribeNext { [unowned self] array in
|
||||
self.users.sendNext(array)
|
||||
self.users.value = array
|
||||
}
|
||||
.addDisposableTo(disposeBag)
|
||||
|
||||
favoriteUsers.sendNext([User(firstName: "Super", lastName: "Man", imageURL: "http://nerdreactor.com/wp-content/uploads/2015/02/Superman1.jpg")])
|
||||
|
||||
favoriteUsers.value = [
|
||||
User(
|
||||
firstName: "Super",
|
||||
lastName: "Man",
|
||||
imageURL: "http://nerdreactor.com/wp-content/uploads/2015/02/Superman1.jpg"
|
||||
)
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
override func setEditing(editing: Bool, animated: Bool) {
|
||||
super.setEditing(editing, animated: animated)
|
||||
tableView.editing = editing
|
||||
}
|
||||
|
||||
|
||||
// MARK: Table view delegate ;)
|
||||
|
||||
|
||||
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
|
||||
let title = dataSource.sectionAtIndex(section)
|
||||
|
||||
|
||||
let label = UILabel(frame: CGRect.zero)
|
||||
// hacky I know :)
|
||||
label.text = " \(title)"
|
||||
label.textColor = UIColor.whiteColor()
|
||||
label.backgroundColor = UIColor.darkGrayColor()
|
||||
label.alpha = 0.9
|
||||
|
||||
|
||||
return label
|
||||
}
|
||||
|
||||
|
||||
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
|
||||
return 40
|
||||
}
|
||||
|
|
@ -128,18 +134,18 @@ class TableViewController: ViewController, UITableViewDelegate {
|
|||
func scrollViewDidScroll(scrollView: UIScrollView) {
|
||||
print("Content offset from delegate \(scrollView.contentOffset)")
|
||||
}
|
||||
|
||||
|
||||
// MARK: Navigation
|
||||
|
||||
|
||||
private func showDetailsForUserAtIndexPath(indexPath: NSIndexPath) {
|
||||
let sb = UIStoryboard(name: "Main", bundle: NSBundle(identifier: "RxExample-iOS"))
|
||||
let vc = sb.instantiateViewControllerWithIdentifier("DetailViewController") as! DetailViewController
|
||||
vc.user = getUser(indexPath)
|
||||
self.navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Work over Variable
|
||||
|
||||
|
||||
func getUser(indexPath: NSIndexPath) -> User {
|
||||
var array: [User]
|
||||
switch indexPath.section {
|
||||
|
|
@ -152,60 +158,60 @@ class TableViewController: ViewController, UITableViewDelegate {
|
|||
}
|
||||
return array[indexPath.row]
|
||||
}
|
||||
|
||||
|
||||
func moveUserFrom(from: NSIndexPath, to: NSIndexPath) {
|
||||
var user: User
|
||||
var fromArray: [User]
|
||||
var toArray: [User]
|
||||
|
||||
|
||||
switch from.section {
|
||||
case 0:
|
||||
fromArray = favoriteUsers.value
|
||||
user = fromArray.removeAtIndex(from.row)
|
||||
favoriteUsers.sendNext(fromArray)
|
||||
favoriteUsers.value = fromArray
|
||||
case 1:
|
||||
fromArray = users.value
|
||||
user = fromArray.removeAtIndex(from.row)
|
||||
users.sendNext(fromArray)
|
||||
users.value = fromArray
|
||||
default:
|
||||
fatalError("Section out of range")
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
switch to.section {
|
||||
case 0:
|
||||
toArray = favoriteUsers.value
|
||||
toArray.insert(user, atIndex: to.row)
|
||||
favoriteUsers.sendNext(toArray)
|
||||
favoriteUsers.value = toArray
|
||||
case 1:
|
||||
toArray = users.value
|
||||
toArray.insert(user, atIndex: to.row)
|
||||
users.sendNext(toArray)
|
||||
users.value = toArray
|
||||
default:
|
||||
fatalError("Section out of range")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func addUser(user: User) {
|
||||
var array = users.value
|
||||
array.append(user)
|
||||
users.sendNext(array)
|
||||
users.value = array
|
||||
}
|
||||
|
||||
|
||||
func removeUser(indexPath: NSIndexPath) {
|
||||
var array: [User]
|
||||
switch indexPath.section {
|
||||
case 0:
|
||||
array = favoriteUsers.value
|
||||
array.removeAtIndex(indexPath.row)
|
||||
favoriteUsers.sendNext(array)
|
||||
favoriteUsers.value = array
|
||||
case 1:
|
||||
array = users.value
|
||||
array.removeAtIndex(indexPath.row)
|
||||
users.sendNext(array)
|
||||
users.value = array
|
||||
default:
|
||||
fatalError("Section out of range")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,32 +14,32 @@ import RxCocoa
|
|||
|
||||
class SearchResultViewModel {
|
||||
let searchResult: WikipediaSearchResult
|
||||
|
||||
|
||||
var title: Observable<String>
|
||||
var imageURLs: Observable<[NSURL]>
|
||||
|
||||
|
||||
let API = DefaultWikipediaAPI.sharedAPI
|
||||
let $: Dependencies = Dependencies.sharedDependencies
|
||||
|
||||
|
||||
init(searchResult: WikipediaSearchResult) {
|
||||
self.searchResult = searchResult
|
||||
|
||||
|
||||
self.title = never()
|
||||
self.imageURLs = never()
|
||||
|
||||
|
||||
let URLs = configureImageURLs()
|
||||
|
||||
self.imageURLs = URLs.catchErrorResumeNext([])
|
||||
self.title = configureTitle(URLs).catchErrorResumeNext("Error during fetching")
|
||||
|
||||
self.imageURLs = URLs.catchErrorJustReturn([])
|
||||
self.title = configureTitle(URLs).catchErrorJustReturn("Error during fetching")
|
||||
}
|
||||
|
||||
|
||||
// private methods
|
||||
|
||||
|
||||
func configureTitle(imageURLs: Observable<[NSURL]>) -> Observable<String> {
|
||||
let searchResult = self.searchResult
|
||||
|
||||
|
||||
let loadingValue: [NSURL]? = nil
|
||||
|
||||
|
||||
return imageURLs
|
||||
.map(Optional.init)
|
||||
.startWith(loadingValue)
|
||||
|
|
@ -52,11 +52,11 @@ class SearchResultViewModel {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func configureImageURLs() -> Observable<[NSURL]> {
|
||||
let searchResult = self.searchResult
|
||||
return API.articleContent(searchResult)
|
||||
.observeSingleOn($.backgroundWorkScheduler)
|
||||
.observeOn($.backgroundWorkScheduler)
|
||||
.map { page in
|
||||
do {
|
||||
return try parseImageURLsfromHTMLSuitableForDisplay(page.text)
|
||||
|
|
@ -64,7 +64,7 @@ class SearchResultViewModel {
|
|||
return []
|
||||
}
|
||||
}
|
||||
.observeSingleOn($.mainScheduler)
|
||||
.observeOn($.mainScheduler)
|
||||
.shareReplay(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class SearchViewModel {
|
|||
API.getSearchResults(query)
|
||||
.retry(3)
|
||||
.startWith([]) // clears results on new search term
|
||||
.catchErrorResumeNext([])
|
||||
.catchErrorJustReturn([])
|
||||
}
|
||||
.switchLatest()
|
||||
.map { results in
|
||||
|
|
|
|||
|
|
@ -14,52 +14,52 @@ import RxCocoa
|
|||
#endif
|
||||
|
||||
public class WikipediaSearchCell: UITableViewCell {
|
||||
|
||||
|
||||
@IBOutlet var titleOutlet: UILabel!
|
||||
@IBOutlet var URLOutlet: UILabel!
|
||||
@IBOutlet var imagesOutlet: UICollectionView!
|
||||
|
||||
|
||||
var disposeBag: DisposeBag!
|
||||
|
||||
|
||||
let imageService = DefaultImageService.sharedImageService
|
||||
|
||||
|
||||
public override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
|
||||
|
||||
self.imagesOutlet.registerNib(UINib(nibName: "WikipediaImageCell", bundle: nil), forCellWithReuseIdentifier: "ImageCell")
|
||||
}
|
||||
|
||||
|
||||
var viewModel: SearchResultViewModel! {
|
||||
didSet {
|
||||
let disposeBag = DisposeBag()
|
||||
|
||||
|
||||
(viewModel?.title ?? just(""))
|
||||
.subscribe(self.titleOutlet.rx_text)
|
||||
.addDisposableTo(disposeBag)
|
||||
|
||||
|
||||
self.URLOutlet.text = viewModel.searchResult.URL.absoluteString ?? ""
|
||||
|
||||
|
||||
viewModel.imageURLs
|
||||
.bindTo(self.imagesOutlet.rx_itemsWithCellIdentifier("ImageCell")) { [unowned self] (_, URL, cell: CollectionViewImageCell) in
|
||||
let loadingPlaceholder: UIImage? = nil
|
||||
|
||||
cell.image = self.imageService.imageFromURL(URL)
|
||||
.map { $0 as UIImage? }
|
||||
.catchErrorResumeNext(nil)
|
||||
.startWith(loadingPlaceholder)
|
||||
let loadingPlaceholder: UIImage? = nil
|
||||
|
||||
cell.image = self.imageService.imageFromURL(URL)
|
||||
.map { $0 as UIImage? }
|
||||
.catchErrorJustReturn(nil)
|
||||
.startWith(loadingPlaceholder)
|
||||
}
|
||||
.addDisposableTo(disposeBag)
|
||||
|
||||
self.disposeBag = disposeBag
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override func prepareForReuse() {
|
||||
super.prepareForReuse()
|
||||
|
||||
|
||||
self.disposeBag = nil
|
||||
}
|
||||
|
||||
|
||||
deinit {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class DefaultWikipediaAPI: WikipediaAPI {
|
|||
let url = NSURL(string: urlContent)!
|
||||
|
||||
return $.URLSession.rx_JSON(url)
|
||||
.observeSingleOn($.backgroundWorkScheduler)
|
||||
.observeOn($.backgroundWorkScheduler)
|
||||
.map { json in
|
||||
guard let json = json as? [AnyObject] else {
|
||||
throw exampleError("Parsing error")
|
||||
|
|
@ -50,7 +50,7 @@ class DefaultWikipediaAPI: WikipediaAPI {
|
|||
|
||||
return try WikipediaSearchResult.parseJSON(json)
|
||||
}
|
||||
.observeSingleOn($.mainScheduler)
|
||||
.observeOn($.mainScheduler)
|
||||
}
|
||||
|
||||
// http://en.wikipedia.org/w/api.php?action=parse&page=rx&format=json
|
||||
|
|
@ -70,6 +70,6 @@ class DefaultWikipediaAPI: WikipediaAPI {
|
|||
|
||||
return try WikipediaPage.parseJSON(json)
|
||||
}
|
||||
.observeSingleOn($.mainScheduler)
|
||||
.observeOn($.mainScheduler)
|
||||
}
|
||||
}
|
||||
|
|
@ -35,7 +35,7 @@ struct WikipediaSearchResult: CustomStringConvertible {
|
|||
let titleAndDescription = Array(Swift.zip(rootArrayTyped[0], rootArrayTyped[1]))
|
||||
let titleDescriptionAndUrl: [((AnyObject, AnyObject), AnyObject)] = Array(Swift.zip(titleAndDescription, rootArrayTyped[2]))
|
||||
|
||||
let searchResults: [RxResult<WikipediaSearchResult>] = titleDescriptionAndUrl.map ( { result -> RxResult<WikipediaSearchResult> in
|
||||
let searchResults: [WikipediaSearchResult] = try titleDescriptionAndUrl.map ( { result -> WikipediaSearchResult in
|
||||
let (first, url) = result
|
||||
let (title, description) = first
|
||||
|
||||
|
|
@ -44,19 +44,17 @@ struct WikipediaSearchResult: CustomStringConvertible {
|
|||
urlString = url as? String
|
||||
|
||||
if titleString == nil || descriptionString == nil || urlString == nil {
|
||||
return failure(WikipediaParseError)
|
||||
throw WikipediaParseError
|
||||
}
|
||||
|
||||
let URL = NSURL(string: urlString!)
|
||||
if URL == nil {
|
||||
return failure(WikipediaParseError)
|
||||
throw WikipediaParseError
|
||||
}
|
||||
|
||||
return success(WikipediaSearchResult(title: titleString!, description: descriptionString!, URL: URL!))
|
||||
return WikipediaSearchResult(title: titleString!, description: descriptionString!, URL: URL!)
|
||||
})
|
||||
|
||||
let values = (searchResults.filter { $0.isSuccess }).map { $0.get() }
|
||||
|
||||
return values
|
||||
return searchResults
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ class DefaultImageService: ImageService {
|
|||
|
||||
func decodeImage(imageData: NSData) -> Observable<Image> {
|
||||
return just(imageData)
|
||||
.observeSingleOn($.backgroundWorkScheduler)
|
||||
.observeOn($.backgroundWorkScheduler)
|
||||
.map { data in
|
||||
let maybeImage = Image(data: data)
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ class DefaultImageService: ImageService {
|
|||
|
||||
return image
|
||||
}
|
||||
.observeSingleOn($.mainScheduler)
|
||||
.observeOn($.mainScheduler)
|
||||
}
|
||||
|
||||
func imageFromURL(URL: NSURL) -> Observable<Image> {
|
||||
|
|
@ -89,6 +89,6 @@ class DefaultImageService: ImageService {
|
|||
return decodedImage.doOn(next: { image in
|
||||
self.imageCache.setObject(image, forKey: URL)
|
||||
})
|
||||
}
|
||||
}.observeOn($.mainScheduler)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
//
|
||||
// AnyObject+Rx.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/28/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public func castOrFail<T>(result: AnyObject!) -> RxResult<T> {
|
||||
if let typedResult = result as? T {
|
||||
return success(typedResult)
|
||||
}
|
||||
else {
|
||||
return failure(CastError)
|
||||
}
|
||||
}
|
||||
|
||||
public func makeOptionalResult<T>(result: T) -> RxResult<T?> {
|
||||
return success(result)
|
||||
}
|
||||
|
|
@ -8,6 +8,12 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Represents disposable resource with state tracking.
|
||||
*/
|
||||
public protocol Cancelable : Disposable {
|
||||
/**
|
||||
- returns: Was resource disposed.
|
||||
*/
|
||||
var disposed: Bool { get }
|
||||
}
|
||||
|
|
@ -8,14 +8,16 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
// In case nobody holds this lock, the work will be queued and executed immediately
|
||||
// on thread that is requesting lock.
|
||||
//
|
||||
// In case there is somebody currently holding that lock, action will be enqueued.
|
||||
// When owned of the lock finishes with it's processing, it will also execute
|
||||
// and pending work.
|
||||
//
|
||||
// That means that enqueued work could possibly be executed later on a different thread.
|
||||
/**
|
||||
In case nobody holds this lock, the work will be queued and executed immediately
|
||||
on thread that is requesting lock.
|
||||
|
||||
In case there is somebody currently holding that lock, action will be enqueued.
|
||||
When owned of the lock finishes with it's processing, it will also execute
|
||||
and pending work.
|
||||
|
||||
That means that enqueued work could possibly be executed later on a different thread.
|
||||
*/
|
||||
class AsyncLock : Disposable {
|
||||
typealias Action = () -> Void
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Simple wrapper for spin lock.
|
||||
*/
|
||||
struct SpinLock {
|
||||
private var _lock = OS_SPINLOCK_INIT
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,14 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Represents an observable sequence wrapper that can be connected and disconnected from its underlying observable sequence.
|
||||
*/
|
||||
public protocol ConnectableObservableType : ObservableType {
|
||||
/**
|
||||
Connects the observable wrapper to its source. All subscribed observers will receive values from the underlying observable sequence as long as the connection is established.
|
||||
|
||||
- returns: Disposable used to disconnect the observable wrapper from its source, causing subscribed observer to stop receiving values from the underlying observable sequence.
|
||||
*/
|
||||
func connect() -> Disposable
|
||||
}
|
||||
|
|
@ -8,22 +8,44 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Class that enables using memory allocations as a means to uniquely identify objects.
|
||||
*/
|
||||
class Identity {
|
||||
// weird things have known to happen with Swift
|
||||
var _forceAllocation: Int32 = 0
|
||||
}
|
||||
|
||||
/**
|
||||
Unique identifier for object added to `Bag`.
|
||||
*/
|
||||
public struct BagKey : Equatable {
|
||||
let uniqueIdentity: Identity?
|
||||
let key: Int
|
||||
}
|
||||
|
||||
/**
|
||||
Compares two `BagKey`s.
|
||||
*/
|
||||
public func == (lhs: BagKey, rhs: BagKey) -> Bool {
|
||||
return lhs.key == rhs.key && lhs.uniqueIdentity === rhs.uniqueIdentity
|
||||
}
|
||||
|
||||
/**
|
||||
Data structure that represents a bag of elements typed `T`.
|
||||
|
||||
Single element can be stored multiple times.
|
||||
|
||||
Time and space complexity of insertion an deletion is O(n).
|
||||
|
||||
It is suitable for storing small number of elements.
|
||||
*/
|
||||
public struct Bag<T> : CustomStringConvertible {
|
||||
/**
|
||||
Type of identifier for inserted elements.
|
||||
*/
|
||||
public typealias KeyType = BagKey
|
||||
|
||||
private typealias ScopeUniqueTokenType = Int
|
||||
|
||||
typealias Entry = (key: BagKey, value: T)
|
||||
|
|
@ -36,16 +58,28 @@ public struct Bag<T> : CustomStringConvertible {
|
|||
|
||||
var pairs = [Entry]()
|
||||
|
||||
/**
|
||||
Creates new empty `Bag`.
|
||||
*/
|
||||
public init() {
|
||||
}
|
||||
|
||||
/**
|
||||
- returns: Bag description.
|
||||
*/
|
||||
public var description : String {
|
||||
get {
|
||||
return "\(self.count) elements in Bag"
|
||||
}
|
||||
}
|
||||
|
||||
public mutating func put(value: T) -> BagKey {
|
||||
/**
|
||||
Inserts `value` into bag.
|
||||
|
||||
- parameter element: Element to insert.
|
||||
- returns: Key that can be used to remove element from bag.
|
||||
*/
|
||||
public mutating func insert(element: T) -> BagKey {
|
||||
nextKey = nextKey &+ 1
|
||||
|
||||
#if DEBUG
|
||||
|
|
@ -59,30 +93,42 @@ public struct Bag<T> : CustomStringConvertible {
|
|||
let key = BagKey(uniqueIdentity: uniqueIdentity, key: nextKey)
|
||||
|
||||
if preallocated_0 == nil {
|
||||
preallocated_0 = (key: key, value: value)
|
||||
preallocated_0 = (key: key, value: element)
|
||||
return key
|
||||
}
|
||||
|
||||
if preallocated_1 == nil {
|
||||
preallocated_1 = (key: key, value: value)
|
||||
preallocated_1 = (key: key, value: element)
|
||||
return key
|
||||
}
|
||||
|
||||
pairs.append(key: key, value: value)
|
||||
pairs.append(key: key, value: element)
|
||||
|
||||
return key
|
||||
}
|
||||
|
||||
/**
|
||||
- returns: Number of elements in bag.
|
||||
*/
|
||||
public var count: Int {
|
||||
return pairs.count + (preallocated_0 != nil ? 1 : 0) + (preallocated_1 != nil ? 1 : 0)
|
||||
}
|
||||
|
||||
/**
|
||||
Removes all elements from bag and clears capacity.
|
||||
*/
|
||||
public mutating func removeAll() {
|
||||
preallocated_0 = nil
|
||||
preallocated_1 = nil
|
||||
pairs.removeAll(keepCapacity: false)
|
||||
}
|
||||
|
||||
/**
|
||||
Removes element with a specific `key` from bag.
|
||||
|
||||
- parameter key: Key that identifies element to remove from bag.
|
||||
- returns: Element that bag contained, or nil in case element was already removed.
|
||||
*/
|
||||
public mutating func removeKey(key: BagKey) -> T? {
|
||||
if preallocated_0?.key == key {
|
||||
let value = preallocated_0!.value
|
||||
|
|
@ -108,6 +154,11 @@ public struct Bag<T> : CustomStringConvertible {
|
|||
}
|
||||
|
||||
extension Bag {
|
||||
/**
|
||||
Enumerates elements inside the bag.
|
||||
|
||||
- parameter action: Enumeration closure.
|
||||
*/
|
||||
public func forEach(@noescape action: (T) -> Void) {
|
||||
let value0 = preallocated_0
|
||||
let value1 = preallocated_1
|
||||
|
|
|
|||
|
|
@ -8,7 +8,10 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
class InifiniteSequence<E> : SequenceType {
|
||||
/**
|
||||
Sequence that repeats `repeatedValue` infinite number of times.
|
||||
*/
|
||||
class InfiniteSequence<E> : SequenceType {
|
||||
typealias Element = E
|
||||
typealias Generator = AnyGenerator<E>
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,18 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Data structure that represents queue.
|
||||
|
||||
Complexity of `enqueue`, `dequeue` is O(1) when number of operations is
|
||||
averaged over N operations.
|
||||
|
||||
Complexity of `peek` is O(1).
|
||||
*/
|
||||
public struct Queue<T>: SequenceType {
|
||||
/**
|
||||
Type of generator.
|
||||
*/
|
||||
public typealias Generator = AnyGenerator<T>
|
||||
|
||||
let resizeFactor = 2
|
||||
|
|
@ -19,6 +30,11 @@ public struct Queue<T>: SequenceType {
|
|||
private var initialCapacity: Int
|
||||
private var version: Int
|
||||
|
||||
/**
|
||||
Creates new queue.
|
||||
|
||||
- parameter capacity: Capacity of newly created queue.
|
||||
*/
|
||||
public init(capacity: Int) {
|
||||
initialCapacity = capacity
|
||||
|
||||
|
|
@ -36,20 +52,29 @@ public struct Queue<T>: SequenceType {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
- returns: Is queue empty.
|
||||
*/
|
||||
public var empty: Bool {
|
||||
get {
|
||||
return count == 0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
- returns: Number of elements inside queue.
|
||||
*/
|
||||
public var count: Int {
|
||||
get {
|
||||
return _count
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
- returns: Element in front of a list of elements to `dequeue`.
|
||||
*/
|
||||
public func peek() -> T {
|
||||
contract(count > 0)
|
||||
precondition(count > 0)
|
||||
|
||||
return storage[dequeueIndex]!
|
||||
}
|
||||
|
|
@ -75,7 +100,12 @@ public struct Queue<T>: SequenceType {
|
|||
storage = newStorage
|
||||
}
|
||||
|
||||
public mutating func enqueue(item: T) {
|
||||
/**
|
||||
Enqueues `element`.
|
||||
|
||||
- parameter element: Element to enqueue.
|
||||
*/
|
||||
public mutating func enqueue(element: T) {
|
||||
version++
|
||||
|
||||
_ = count == storage.count
|
||||
|
|
@ -83,7 +113,7 @@ public struct Queue<T>: SequenceType {
|
|||
resizeTo(storage.count * resizeFactor)
|
||||
}
|
||||
|
||||
storage[pushNextIndex] = item
|
||||
storage[pushNextIndex] = element
|
||||
pushNextIndex++
|
||||
_count = _count + 1
|
||||
|
||||
|
|
@ -93,9 +123,9 @@ public struct Queue<T>: SequenceType {
|
|||
}
|
||||
|
||||
private mutating func dequeueElementOnly() -> T {
|
||||
version++
|
||||
precondition(count > 0)
|
||||
|
||||
contract(count > 0)
|
||||
version++
|
||||
|
||||
let index = dequeueIndex
|
||||
let value = storage[index]!
|
||||
|
|
@ -107,6 +137,11 @@ public struct Queue<T>: SequenceType {
|
|||
return value
|
||||
}
|
||||
|
||||
/**
|
||||
Dequeues element or throws an exception in case queue is empty.
|
||||
|
||||
- returns: Dequeued element.
|
||||
*/
|
||||
public mutating func dequeue() -> T {
|
||||
let value = dequeueElementOnly()
|
||||
|
||||
|
|
@ -118,6 +153,9 @@ public struct Queue<T>: SequenceType {
|
|||
return value
|
||||
}
|
||||
|
||||
/**
|
||||
- returns: Generator of contained elements.
|
||||
*/
|
||||
public func generate() -> Generator {
|
||||
var i = dequeueIndex
|
||||
var count = _count
|
||||
|
|
|
|||
|
|
@ -8,7 +8,12 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
public protocol Disposable : class
|
||||
{
|
||||
/**
|
||||
Respresents disposable resource.
|
||||
*/
|
||||
public protocol Disposable {
|
||||
/**
|
||||
Dispose resource.
|
||||
*/
|
||||
func dispose()
|
||||
}
|
||||
|
|
@ -8,12 +8,20 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
public class AnonymousDisposable : DisposeBase, Cancelable {
|
||||
/**
|
||||
Represents an Action-based disposable.
|
||||
|
||||
When dispose method is called, disposal action will be dereferenced.
|
||||
*/
|
||||
public final class AnonymousDisposable : DisposeBase, Cancelable {
|
||||
public typealias DisposeAction = () -> Void
|
||||
|
||||
var lock = SpinLock()
|
||||
var disposeAction: DisposeAction?
|
||||
|
||||
/**
|
||||
- returns: Was resource disposed.
|
||||
*/
|
||||
public var disposed: Bool {
|
||||
get {
|
||||
return lock.calculateLocked {
|
||||
|
|
@ -22,11 +30,21 @@ public class AnonymousDisposable : DisposeBase, Cancelable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Constructs a new disposable with the given action used for disposal.
|
||||
|
||||
- parameter disposeAction: Disposal action which will be run upon calling `dispose`.
|
||||
*/
|
||||
public init(_ disposeAction: DisposeAction) {
|
||||
self.disposeAction = disposeAction
|
||||
super.init()
|
||||
}
|
||||
|
||||
/**
|
||||
Calls the disposal action if and only if the current instance hasn't been disposed yet.
|
||||
|
||||
After invoking disposal action, disposal action will be dereferenced.
|
||||
*/
|
||||
public func dispose() {
|
||||
let toDispose: DisposeAction? = lock.calculateLocked {
|
||||
let action = self.disposeAction
|
||||
|
|
|
|||
|
|
@ -8,25 +8,42 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
class BinaryDisposable : DisposeBase, Cancelable {
|
||||
/**
|
||||
Represents two disposable resources that are disposed together.
|
||||
*/
|
||||
public final class BinaryDisposable : DisposeBase, Cancelable {
|
||||
var disposable1: Disposable?
|
||||
var disposable2: Disposable?
|
||||
|
||||
var _disposed: Int32 = 0
|
||||
|
||||
var disposed: Bool {
|
||||
/**
|
||||
- returns: Was resource disposed.
|
||||
*/
|
||||
public var disposed: Bool {
|
||||
get {
|
||||
return _disposed > 0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Constructs new binary disposable from two disposables.
|
||||
|
||||
- parameter disposable1: First disposable
|
||||
- parameter disposable2: Second disposable
|
||||
*/
|
||||
init(_ disposable1: Disposable, _ disposable2: Disposable) {
|
||||
self.disposable1 = disposable1
|
||||
self.disposable2 = disposable2
|
||||
super.init()
|
||||
}
|
||||
|
||||
func dispose() {
|
||||
/**
|
||||
Calls the disposal action if and only if the current instance hasn't been disposed yet.
|
||||
|
||||
After invoking disposal action, disposal action will be dereferenced.
|
||||
*/
|
||||
public func dispose() {
|
||||
if OSAtomicCompareAndSwap32(0, 1, &_disposed) {
|
||||
disposable1?.dispose()
|
||||
disposable2?.dispose()
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
//
|
||||
// CancelDisposable.swift
|
||||
// RxSwift
|
||||
//
|
||||
// Created by Krunoslav Zaher on 7/25/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class BooleanDisposable : Cancelable {
|
||||
private var _disposed: Bool = false
|
||||
public var disposed: Bool {
|
||||
get {
|
||||
return _disposed
|
||||
}
|
||||
}
|
||||
|
||||
public init() {
|
||||
|
||||
}
|
||||
|
||||
public func dispose() {
|
||||
_disposed = true
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,9 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Represents a group of disposable resources that are disposed together.
|
||||
*/
|
||||
public class CompositeDisposable : DisposeBase, Disposable, Cancelable {
|
||||
public typealias DisposeKey = Bag<Disposable>.KeyType
|
||||
|
||||
|
|
@ -25,28 +28,44 @@ public class CompositeDisposable : DisposeBase, Disposable, Cancelable {
|
|||
public override init() {
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes a new instance of composite disposable with the specified number of disposables.
|
||||
*/
|
||||
public init(_ disposable1: Disposable, _ disposable2: Disposable) {
|
||||
self.disposables!.put(disposable1)
|
||||
self.disposables!.put(disposable2)
|
||||
self.disposables!.insert(disposable1)
|
||||
self.disposables!.insert(disposable2)
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes a new instance of composite disposable with the specified number of disposables.
|
||||
*/
|
||||
public init(_ disposable1: Disposable, _ disposable2: Disposable, _ disposable3: Disposable) {
|
||||
disposables!.put(disposable1)
|
||||
disposables!.put(disposable2)
|
||||
disposables!.put(disposable3)
|
||||
disposables!.insert(disposable1)
|
||||
disposables!.insert(disposable2)
|
||||
disposables!.insert(disposable3)
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes a new instance of composite disposable with the specified number of disposables.
|
||||
*/
|
||||
public init(disposables: [Disposable]) {
|
||||
for disposable in disposables {
|
||||
self.disposables!.put(disposable)
|
||||
self.disposables!.insert(disposable)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Adds a disposable to the CompositeDisposable or disposes the disposable if the CompositeDisposable is disposed.
|
||||
|
||||
- parameter disposable: Disposable to add.
|
||||
- returns: Key that can be used to remove disposable from composite disposable. In case dispose bag was already
|
||||
disposed `nil` will be returned.
|
||||
*/
|
||||
public func addDisposable(disposable: Disposable) -> DisposeKey? {
|
||||
// this should be let
|
||||
// bucause of compiler bug it's var
|
||||
let key = self.lock.calculateLocked { () -> DisposeKey? in
|
||||
return disposables?.put(disposable)
|
||||
return disposables?.insert(disposable)
|
||||
}
|
||||
|
||||
if key == nil {
|
||||
|
|
@ -56,6 +75,9 @@ public class CompositeDisposable : DisposeBase, Disposable, Cancelable {
|
|||
return key
|
||||
}
|
||||
|
||||
/**
|
||||
- returns: Gets the number of disposables contained in the `CompositeDisposable`.
|
||||
*/
|
||||
public var count: Int {
|
||||
get {
|
||||
return self.lock.calculateLocked {
|
||||
|
|
@ -64,6 +86,11 @@ public class CompositeDisposable : DisposeBase, Disposable, Cancelable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Removes and disposes the disposable identified by `disposeKey` from the CompositeDisposable.
|
||||
|
||||
- parameter disposeKey: Key used to identify disposable to be removed.
|
||||
*/
|
||||
public func removeDisposable(disposeKey: DisposeKey) {
|
||||
let disposable = self.lock.calculateLocked { () -> Disposable? in
|
||||
return disposables?.removeKey(disposeKey)
|
||||
|
|
@ -74,6 +101,9 @@ public class CompositeDisposable : DisposeBase, Disposable, Cancelable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Disposes all disposables in the group and removes them from the group.
|
||||
*/
|
||||
public func dispose() {
|
||||
let oldDisposables = self.lock.calculateLocked { () -> Bag<Disposable>? in
|
||||
let disposeBag = disposables
|
||||
|
|
|
|||
|
|
@ -9,23 +9,45 @@
|
|||
import Foundation
|
||||
|
||||
extension Disposable {
|
||||
/**
|
||||
Adds `self` to `bag`.
|
||||
|
||||
- parameter bag: `DisposeBag` to add `self` to.
|
||||
*/
|
||||
public func addDisposableTo(bag: DisposeBag) {
|
||||
bag.addDisposable(self)
|
||||
}
|
||||
}
|
||||
|
||||
// Thread safe bag that disposes disposables that have been added to it on `deinit`.
|
||||
// This returns ARC (RAII) like resource management to `RxSwift`.
|
||||
/**
|
||||
Thread safe bag that disposes added disposables on `deinit`.
|
||||
|
||||
This returns ARC (RAII) like resource management to `RxSwift`.
|
||||
|
||||
In case contained disposables need to be disposed, just deference dispose bag
|
||||
or create new one in it's place.
|
||||
|
||||
self.existingDisposeBag = DisposeBag()
|
||||
|
||||
In case explicit disposal is necessary, there is also `CompositeDisposable`.
|
||||
*/
|
||||
public class DisposeBag: DisposeBase {
|
||||
|
||||
private var lock = SpinLock()
|
||||
var disposables = [Disposable]()
|
||||
var disposed = false
|
||||
|
||||
/**
|
||||
Constructs new empty dispose bag.
|
||||
*/
|
||||
public override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
/**
|
||||
Adds `disposable` to be disposed when dispose bag is being deinited.
|
||||
|
||||
- parameter disposable: Disposable to add.
|
||||
*/
|
||||
public func addDisposable(disposable: Disposable) {
|
||||
let dispose = lock.calculateLocked { () -> Bool in
|
||||
if disposed {
|
||||
|
|
@ -42,6 +64,9 @@ public class DisposeBag: DisposeBase {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
This is internal on purpose, take a look at `CompositeDisposable` instead.
|
||||
*/
|
||||
func dispose() {
|
||||
let oldDisposables = lock.calculateLocked { () -> [Disposable] in
|
||||
let disposables = self.disposables
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Base class for all disposables.
|
||||
*/
|
||||
public class DisposeBase {
|
||||
init() {
|
||||
#if TRACE_RESOURCES
|
||||
|
|
|
|||
|
|
@ -8,16 +8,25 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
// Disposable that does nothing
|
||||
// Nop = No Operation
|
||||
/**
|
||||
Represents a disposable that does nothing on disposal.
|
||||
|
||||
Nop = No Operation
|
||||
*/
|
||||
public class NopDisposable : Disposable {
|
||||
|
||||
/**
|
||||
Singleton instance of `NopDisposable`.
|
||||
*/
|
||||
public static let instance: Disposable = NopDisposable()
|
||||
|
||||
init() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Does nothing.
|
||||
*/
|
||||
public func dispose() {
|
||||
}
|
||||
}
|
||||
|
|
@ -8,12 +8,15 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Represents a disposable resource whose disposal invocation will be scheduled on the specified scheduler.
|
||||
*/
|
||||
public class ScheduledDisposable : Cancelable {
|
||||
public let scheduler: ImmediateScheduler
|
||||
var _disposable: Disposable?
|
||||
var lock = SpinLock()
|
||||
|
||||
public var disposable: Disposable {
|
||||
var disposable: Disposable {
|
||||
get {
|
||||
return lock.calculateLocked {
|
||||
_disposable ?? NopDisposable.instance
|
||||
|
|
@ -21,6 +24,9 @@ public class ScheduledDisposable : Cancelable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
- returns: Was resource disposed.
|
||||
*/
|
||||
public var disposed: Bool {
|
||||
get {
|
||||
return lock.calculateLocked {
|
||||
|
|
@ -29,11 +35,20 @@ public class ScheduledDisposable : Cancelable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes a new instance of the `ScheduledDisposable` that uses a `scheduler` on which to dispose the `disposable`.
|
||||
|
||||
- parameter scheduler: Scheduler where the disposable resource will be disposed on.
|
||||
- parameter disposable: Disposable resource to dispose on the given scheduler.
|
||||
*/
|
||||
init(scheduler: ImmediateScheduler, disposable: Disposable) {
|
||||
self.scheduler = scheduler
|
||||
self._disposable = disposable
|
||||
}
|
||||
|
||||
/**
|
||||
Disposes the wrapped disposable on the provided scheduler.
|
||||
*/
|
||||
public func dispose() {
|
||||
scheduler.schedule(()) {
|
||||
self.disposeInner()
|
||||
|
|
@ -41,7 +56,7 @@ public class ScheduledDisposable : Cancelable {
|
|||
}
|
||||
}
|
||||
|
||||
public func disposeInner() {
|
||||
func disposeInner() {
|
||||
lock.performLocked {
|
||||
if let disposable = _disposable {
|
||||
disposable.dispose()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
//
|
||||
// ScopedDisposable.swift
|
||||
// RxSwift
|
||||
//
|
||||
// Created by Krunoslav Zaher on 5/2/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension Disposable {
|
||||
/**
|
||||
Returns `ScopedDispose` that will dispose `self` when execution exits current block.
|
||||
|
||||
**If the reference to returned instance isn't named, it will be deallocated
|
||||
immediately and subscription will be immediately disposed.**
|
||||
|
||||
Example usage:
|
||||
|
||||
let disposeOnExit = disposable.scopedDispose()
|
||||
|
||||
- returns: `ScopedDisposable` that will dispose `self` on `deinit`.
|
||||
*/
|
||||
public func scopedDispose() -> ScopedDisposable {
|
||||
return ScopedDisposable(disposable: self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
`ScopedDisposable` will dispose `disposable` on `deinit`.
|
||||
|
||||
This returns ARC (RAII) like resource management to `RxSwift`.
|
||||
*/
|
||||
public class ScopedDisposable : DisposeBase {
|
||||
var disposable: Disposable?
|
||||
|
||||
/**
|
||||
Initializes new instance with a single disposable.
|
||||
|
||||
- parameter disposable: `Disposable` that will be disposed on scope exit.
|
||||
*/
|
||||
public init(disposable: Disposable) {
|
||||
self.disposable = disposable
|
||||
}
|
||||
|
||||
/**
|
||||
This is intentionally private.
|
||||
*/
|
||||
func dispose() {
|
||||
self.disposable?.dispose()
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.dispose()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
//
|
||||
// ScopedDispose.swift
|
||||
// RxSwift
|
||||
//
|
||||
// Created by Krunoslav Zaher on 5/2/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension Disposable {
|
||||
public var scopedDispose: ScopedDispose {
|
||||
return ScopedDispose(disposable: self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// It will dispose `disposable` on `deinit`.
|
||||
// This returns ARC (RAII) like resource management to `RxSwift`.
|
||||
public class ScopedDispose : DisposeBase {
|
||||
var disposable: Disposable?
|
||||
|
||||
public init(disposable: Disposable) {
|
||||
self.disposable = disposable
|
||||
}
|
||||
|
||||
func dispose() {
|
||||
// disposables are already thread safe
|
||||
self.disposable?.dispose()
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.dispose()
|
||||
}
|
||||
}
|
||||
|
|
@ -8,29 +8,40 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Represents a disposable resource whose underlying disposable resource can be replaced by another disposable resource, causing automatic disposal of the previous underlying disposable resource.
|
||||
*/
|
||||
public class SerialDisposable : DisposeBase, Cancelable {
|
||||
typealias State = (
|
||||
current: Disposable?,
|
||||
disposed: Bool
|
||||
)
|
||||
|
||||
var lock = SpinLock()
|
||||
var state: State = (
|
||||
current: nil,
|
||||
disposed: false
|
||||
)
|
||||
|
||||
// state
|
||||
var _current = nil as Disposable?
|
||||
var _disposed = false
|
||||
|
||||
/**
|
||||
- returns: Was resource disposed.
|
||||
*/
|
||||
public var disposed: Bool {
|
||||
get {
|
||||
return state.disposed
|
||||
return _disposed
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes a new instance of the `SerialDisposable`.
|
||||
*/
|
||||
override public init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
var disposable: Disposable {
|
||||
/**
|
||||
Gets or sets the underlying disposable.
|
||||
|
||||
Assigning this property disposes the previous disposable object.
|
||||
|
||||
If the `SerialDisposable` has already been disposed, assignment to this property causes immediate disposal of the given disposable object.
|
||||
*/
|
||||
public var disposable: Disposable {
|
||||
get {
|
||||
return self.lock.calculateLocked {
|
||||
return self.disposable
|
||||
|
|
@ -38,12 +49,12 @@ public class SerialDisposable : DisposeBase, Cancelable {
|
|||
}
|
||||
set (newDisposable) {
|
||||
let disposable: Disposable? = self.lock.calculateLocked {
|
||||
if state.disposed {
|
||||
if _disposed {
|
||||
return newDisposable
|
||||
}
|
||||
else {
|
||||
let toDispose = state.current
|
||||
state.current = newDisposable
|
||||
let toDispose = _current
|
||||
_current = newDisposable
|
||||
return toDispose
|
||||
}
|
||||
}
|
||||
|
|
@ -54,14 +65,17 @@ public class SerialDisposable : DisposeBase, Cancelable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Disposes the underlying disposable as well as all future replacements.
|
||||
*/
|
||||
public func dispose() {
|
||||
let disposable: Disposable? = self.lock.calculateLocked {
|
||||
if state.disposed {
|
||||
if _disposed {
|
||||
return nil
|
||||
}
|
||||
else {
|
||||
state.disposed = true
|
||||
return state.current
|
||||
_disposed = true
|
||||
return _current
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,13 +8,22 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Represents a disposable resource which only allows a single assignment of its underlying disposable resource.
|
||||
|
||||
If an underlying disposable resource has already been set, future attempts to set the underlying disposable resource will throw an exception.
|
||||
*/
|
||||
public class SingleAssignmentDisposable : DisposeBase, Disposable, Cancelable {
|
||||
var lock = SpinLock()
|
||||
|
||||
// state
|
||||
var _disposed = false
|
||||
var _disposableSet = false
|
||||
var _disposable = nil as Disposable?
|
||||
|
||||
/**
|
||||
- returns: A value that indicates whether the object is disposed.
|
||||
*/
|
||||
public var disposed: Bool {
|
||||
get {
|
||||
return lock.calculateLocked {
|
||||
|
|
@ -23,10 +32,18 @@ public class SingleAssignmentDisposable : DisposeBase, Disposable, Cancelable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes a new instance of the `SingleAssignmentDisposable`.
|
||||
*/
|
||||
public override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
/**
|
||||
Gets or sets the underlying disposable. After disposal, the result of getting this property is undefined.
|
||||
|
||||
**Throws exception if the `SingleAssignmentDisposable` has already been assigned to.**
|
||||
*/
|
||||
public var disposable: Disposable {
|
||||
get {
|
||||
return lock.calculateLocked {
|
||||
|
|
@ -56,6 +73,9 @@ public class SingleAssignmentDisposable : DisposeBase, Disposable, Cancelable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Disposes the underlying disposable.
|
||||
*/
|
||||
public func dispose() {
|
||||
let disposable: Disposable? = lock.calculateLocked {
|
||||
_disposed = true
|
||||
|
|
|
|||
|
|
@ -11,16 +11,36 @@ import Foundation
|
|||
let RxErrorDomain = "RxErrorDomain"
|
||||
let RxCompositeFailures = "RxCompositeFailures"
|
||||
|
||||
/**
|
||||
Generic Rx error codes.
|
||||
|
||||
- Unknown: Unknown error occured
|
||||
- Cast: Error during Casting
|
||||
- Disposed: Performing an action on disposed object
|
||||
*/
|
||||
public enum RxErrorCode : Int {
|
||||
case Unknown = 0
|
||||
case Cast = 2
|
||||
case Disposed = 3
|
||||
}
|
||||
|
||||
public let UnknownError = NSError(domain: RxErrorDomain, code: RxErrorCode.Unknown.rawValue, userInfo: nil)
|
||||
public let CastError = NSError(domain: RxErrorDomain, code: RxErrorCode.Cast.rawValue, userInfo: nil)
|
||||
public let DisposedError = NSError(domain: RxErrorDomain, code: RxErrorCode.Disposed.rawValue, userInfo: nil)
|
||||
/**
|
||||
Singleton instances of RxErrors
|
||||
*/
|
||||
public struct RxError {
|
||||
/**
|
||||
Singleton instance of Unknown Error
|
||||
*/
|
||||
public static let UnknownError = NSError(domain: RxErrorDomain, code: RxErrorCode.Unknown.rawValue, userInfo: nil)
|
||||
|
||||
func removingObserverFailed() {
|
||||
rxFatalError("Removing observer for key failed")
|
||||
}
|
||||
/**
|
||||
Singleton instance of error during casting
|
||||
*/
|
||||
public static let CastError = NSError(domain: RxErrorDomain, code: RxErrorCode.Cast.rawValue, userInfo: nil)
|
||||
|
||||
/**
|
||||
Singleton instance of doing something on a disposed object
|
||||
*/
|
||||
public static let DisposedError = NSError(domain: RxErrorDomain, code: RxErrorCode.Disposed.rawValue, userInfo: nil)
|
||||
|
||||
}
|
||||
|
|
@ -10,13 +10,30 @@ import Foundation
|
|||
|
||||
|
||||
/**
|
||||
* Represents event that happened
|
||||
Represents sequence event
|
||||
|
||||
Sequence grammar:
|
||||
Next\* (Error | Completed)
|
||||
*/
|
||||
public enum Event<Element> : CustomStringConvertible {
|
||||
case Next(Element) // next element of a sequence
|
||||
case Error(ErrorType) // sequence failed with error
|
||||
case Completed // sequence terminated successfully
|
||||
/**
|
||||
Next element is produced
|
||||
*/
|
||||
case Next(Element)
|
||||
|
||||
/**
|
||||
Sequence terminates with error
|
||||
*/
|
||||
case Error(ErrorType)
|
||||
|
||||
/**
|
||||
Sequence completes sucessfully
|
||||
*/
|
||||
case Completed
|
||||
|
||||
/**
|
||||
- returns: Description of event
|
||||
*/
|
||||
public var description: String {
|
||||
get {
|
||||
switch self {
|
||||
|
|
@ -31,28 +48,29 @@ public enum Event<Element> : CustomStringConvertible {
|
|||
}
|
||||
}
|
||||
|
||||
public func eventType<T>(event: Event<T>) -> String {
|
||||
switch event {
|
||||
case .Next:
|
||||
return "Next: \(event)"
|
||||
case .Completed:
|
||||
return "Completed"
|
||||
case .Error(let error):
|
||||
return "Error \(error)"
|
||||
}
|
||||
}
|
||||
/**
|
||||
Compares two events. They are equal if they are both the same member of `Event` enumeration.
|
||||
|
||||
In case `Error` events are being compared, they are equal in case their `NSError` representations are equal (domain and code).
|
||||
*/
|
||||
public func == <T: Equatable>(lhs: Event<T>, rhs: Event<T>) -> Bool {
|
||||
switch (lhs, rhs) {
|
||||
case (.Completed, .Completed): return true
|
||||
// really stupid fix for now
|
||||
case (.Error(let e1), .Error(let e2)): return "\(e1)" == "\(e2)"
|
||||
case (.Error(let e1), .Error(let e2)):
|
||||
let error1 = e1 as NSError
|
||||
let error2 = e2 as NSError
|
||||
|
||||
return error1.domain == error2.domain
|
||||
&& error1.code == error2.code
|
||||
case (.Next(let v1), .Next(let v2)): return v1 == v2
|
||||
default: return false
|
||||
}
|
||||
}
|
||||
|
||||
extension Event {
|
||||
/**
|
||||
- returns: Is `Completed` or `Error` event
|
||||
*/
|
||||
public var isStopEvent: Bool {
|
||||
get {
|
||||
switch self {
|
||||
|
|
@ -64,7 +82,10 @@ extension Event {
|
|||
}
|
||||
}
|
||||
|
||||
public var value: Element? {
|
||||
/**
|
||||
- returns: If `Next` event, returns element value.
|
||||
*/
|
||||
public var element: Element? {
|
||||
get {
|
||||
switch self {
|
||||
case .Next(let value):
|
||||
|
|
@ -75,6 +96,9 @@ extension Event {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
- returns: If `Error` event, returns error.
|
||||
*/
|
||||
public var error: ErrorType? {
|
||||
get {
|
||||
switch self {
|
||||
|
|
|
|||
|
|
@ -8,17 +8,35 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
|
||||
/**
|
||||
Represents an object that immediately schedules units of work.
|
||||
*/
|
||||
public protocol ImmediateScheduler {
|
||||
/**
|
||||
Schedules an action to be executed immediatelly.
|
||||
|
||||
- parameter state: State passed to the action to be executed.
|
||||
- parameter action: Action to be executed.
|
||||
- returns: The disposable object used to cancel the scheduled action (best effort).
|
||||
*/
|
||||
func schedule<StateType>(state: StateType, action: (StateType) -> Disposable) -> Disposable
|
||||
}
|
||||
|
||||
extension ImmediateScheduler {
|
||||
/**
|
||||
Schedules an action to be executed recursively.
|
||||
|
||||
- parameter state: State passed to the action to be executed.
|
||||
- parameter action: Action to execute recursively. The last parameter passed to the action is used to trigger recursive scheduling of the action, passing in recursive invocation state.
|
||||
- returns: The disposable object used to cancel the scheduled action (best effort).
|
||||
*/
|
||||
public func scheduleRecursively<State>(state: State, action: (state: State, recurse: (State) -> Void) -> Void) -> Disposable {
|
||||
let recursiveScheduler = RecursiveImmediateSchedulerOf(action: action, scheduler: self)
|
||||
|
||||
recursiveScheduler.schedule(state)
|
||||
|
||||
return recursiveScheduler
|
||||
return AnonymousDisposable {
|
||||
recursiveScheduler.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,12 @@
|
|||
import Foundation
|
||||
|
||||
extension ObservableType {
|
||||
/**
|
||||
Subscribes an event handler to an observable sequence.
|
||||
|
||||
- parameter on: Action to invoke for each event in the observable sequence.
|
||||
- returns: Subscription object used to unsubscribe from the observable sequence.
|
||||
*/
|
||||
public func subscribe(on: (event: Event<E>) -> Void)
|
||||
-> Disposable {
|
||||
let observer = AnonymousObserver { e in
|
||||
|
|
@ -17,23 +23,52 @@ extension ObservableType {
|
|||
return self.subscribeSafe(observer)
|
||||
}
|
||||
|
||||
/**
|
||||
Subscribes an element handler, an error handler, a completion handler and disposed handler to an observable sequence.
|
||||
|
||||
- parameter next: Action to invoke for each element in the observable sequence.
|
||||
- parameter error: Action to invoke upon errored termination of the observable sequence.
|
||||
- parameter completed: Action to invoke upon graceful termination of the observable sequence.
|
||||
- parameter disposed: 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)
|
||||
- returns: Subscription object used to unsubscribe from the observable sequence.
|
||||
*/
|
||||
public func subscribe(next next: ((E) -> Void)? = nil, error: ((ErrorType) -> Void)? = nil, completed: (() -> Void)? = nil, disposed: (() -> Void)? = nil)
|
||||
-> Disposable {
|
||||
|
||||
let disposable: Disposable
|
||||
|
||||
if let disposed = disposed {
|
||||
disposable = AnonymousDisposable(disposed)
|
||||
}
|
||||
else {
|
||||
disposable = NopDisposable.instance
|
||||
}
|
||||
|
||||
let observer = AnonymousObserver<E> { e in
|
||||
switch e {
|
||||
case .Next(let value):
|
||||
next?(value)
|
||||
case .Error(let e):
|
||||
error?(e)
|
||||
disposed?()
|
||||
disposable.dispose()
|
||||
case .Completed:
|
||||
completed?()
|
||||
disposed?()
|
||||
disposable.dispose()
|
||||
}
|
||||
}
|
||||
return self.subscribeSafe(observer)
|
||||
return BinaryDisposable(
|
||||
self.subscribeSafe(observer),
|
||||
disposable
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Subscribes an element handler to an observable sequence.
|
||||
|
||||
- parameter onNext: Action to invoke for each element in the observable sequence.
|
||||
- returns: Subscription object used to unsubscribe from the observable sequence.
|
||||
*/
|
||||
public func subscribeNext(onNext: (E) -> Void)
|
||||
-> Disposable {
|
||||
let observer = AnonymousObserver<E> { e in
|
||||
|
|
@ -47,6 +82,12 @@ extension ObservableType {
|
|||
return self.subscribeSafe(observer)
|
||||
}
|
||||
|
||||
/**
|
||||
Subscribes an error handler to an observable sequence.
|
||||
|
||||
- parameter onRrror: Action to invoke upon errored termination of the observable sequence.
|
||||
- returns: Subscription object used to unsubscribe from the observable sequence.
|
||||
*/
|
||||
public func subscribeError(onError: (ErrorType) -> Void)
|
||||
-> Disposable {
|
||||
let observer = AnonymousObserver<E> { e in
|
||||
|
|
@ -60,6 +101,12 @@ extension ObservableType {
|
|||
return self.subscribeSafe(observer)
|
||||
}
|
||||
|
||||
/**
|
||||
Subscribes a completion handler to an observable sequence.
|
||||
|
||||
- parameter onCompleted: Action to invoke upon graceful termination of the observable sequence.
|
||||
- returns: Subscription object used to unsubscribe from the observable sequence.
|
||||
*/
|
||||
public func subscribeCompleted(onCompleted: () -> Void)
|
||||
-> Disposable {
|
||||
let observer = AnonymousObserver<E> { e in
|
||||
|
|
@ -75,8 +122,10 @@ extension ObservableType {
|
|||
}
|
||||
|
||||
public extension ObservableType {
|
||||
// All internal subscribe calls go through this method
|
||||
public func subscribeSafe<O: ObserverType where O.E == E>(observer: O) -> Disposable {
|
||||
/**
|
||||
All internal subscribe calls go through this method
|
||||
*/
|
||||
func subscribeSafe<O: ObserverType where O.E == E>(observer: O) -> Disposable {
|
||||
return self.subscribe(observer)
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,15 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
A type-erased `ObservableType`.
|
||||
|
||||
It represents a push style sequence.
|
||||
*/
|
||||
public class Observable<Element> : ObservableType {
|
||||
/**
|
||||
Type of elements in sequence.
|
||||
*/
|
||||
public typealias E = Element
|
||||
|
||||
public init() {
|
||||
|
|
@ -17,7 +25,6 @@ public class Observable<Element> : ObservableType {
|
|||
#endif
|
||||
}
|
||||
|
||||
/// Subscribes `observer` to receive events from this observable
|
||||
public func subscribe<O: ObserverType where O.E == E>(observer: O) -> Disposable {
|
||||
return abstractMethod()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,11 +8,42 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Represents a push style sequence.
|
||||
*/
|
||||
public protocol ObservableType {
|
||||
/**
|
||||
Type of elements in sequence.
|
||||
*/
|
||||
typealias E
|
||||
|
||||
/// Subscribes `observer` to receive events from this observable
|
||||
func subscribe<O: ObserverType where O.E == E>(observer: O) -> Disposable
|
||||
/**
|
||||
Subscribes `observer` to receive events for this sequence.
|
||||
|
||||
### Grammar
|
||||
|
||||
**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
|
||||
|
||||
It is possible that events are sent from different threads, but no two events can be sent concurrently to
|
||||
`observer`.
|
||||
|
||||
### Resource Management
|
||||
|
||||
When sequence sends `Complete` or `Error` event all internal resources that compute sequence elements
|
||||
will be freed.
|
||||
|
||||
To cancel production of sequence elements and free resources immediatelly, call `dispose` on returned
|
||||
subscription.
|
||||
|
||||
- returns: Subscription for `observer` that can be used to cancel production of sequence elements and free resources.
|
||||
*/
|
||||
func subscribe<O: ObserverType where O.E == E>(observer: O) -> Disposable
|
||||
|
||||
/**
|
||||
- returns: Canonical interface for push style sequence
|
||||
*/
|
||||
func asObservable() -> Observable<E>
|
||||
}
|
||||
|
|
@ -95,53 +95,6 @@ class Catch<Element> : Producer<Element> {
|
|||
}
|
||||
}
|
||||
|
||||
// catch to result
|
||||
|
||||
// O: ObserverType caused compiler crashes, so let's leave that for now
|
||||
class CatchToResultSink<ElementType> : Sink<ObserverOf<RxResult<ElementType>>>, ObserverType {
|
||||
typealias E = ElementType
|
||||
typealias Parent = CatchToResult<E>
|
||||
|
||||
let parent: Parent
|
||||
|
||||
init(parent: Parent, observer: ObserverOf<RxResult<E>>, cancel: Disposable) {
|
||||
self.parent = parent
|
||||
super.init(observer: observer, cancel: cancel)
|
||||
}
|
||||
|
||||
func run() -> Disposable {
|
||||
return parent.source.subscribeSafe(self)
|
||||
}
|
||||
|
||||
func on(event: Event<E>) {
|
||||
switch event {
|
||||
case .Next(let value):
|
||||
observer?.on(.Next(success(value)))
|
||||
case .Completed:
|
||||
observer?.on(.Completed)
|
||||
self.dispose()
|
||||
case .Error(let error):
|
||||
observer?.on(.Next(failure(error)))
|
||||
observer?.on(.Completed)
|
||||
self.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CatchToResult<Element> : Producer <RxResult<Element>> {
|
||||
let source: Observable<Element>
|
||||
|
||||
init(source: Observable<Element>) {
|
||||
self.source = source
|
||||
}
|
||||
|
||||
override func run<O: ObserverType where O.E == RxResult<Element>>(observer: O, cancel: Disposable, setSink: (Disposable) -> Void) -> Disposable {
|
||||
let sink = CatchToResultSink(parent: self, observer: observer.asObserver(), cancel: cancel)
|
||||
setSink(sink)
|
||||
return sink.run()
|
||||
}
|
||||
}
|
||||
|
||||
// catch enumerable
|
||||
|
||||
class CatchSequenceSink<S: SequenceType, O: ObserverType where S.Generator.Element : ObservableType, S.Generator.Element.E == O.E> : TailRecursiveSink<S, O> {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,12 @@ import Foundation
|
|||
|
||||
// 2
|
||||
|
||||
/**
|
||||
Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences produces an element.
|
||||
|
||||
- parameter resultSelector: Function to invoke whenever any of the sources produces an element.
|
||||
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
|
||||
*/
|
||||
public func combineLatest<O1: ObservableType, O2: ObservableType, R>
|
||||
(source1: O1, _ source2: O2, _ resultSelector: (O1.E, O2.E) throws -> R)
|
||||
-> Observable<R> {
|
||||
|
|
@ -84,6 +90,12 @@ class CombineLatest2<E1, E2, R> : Producer<R> {
|
|||
|
||||
// 3
|
||||
|
||||
/**
|
||||
Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences produces an element.
|
||||
|
||||
- parameter resultSelector: Function to invoke whenever any of the sources produces an element.
|
||||
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
|
||||
*/
|
||||
public func combineLatest<O1: ObservableType, O2: ObservableType, O3: ObservableType, R>
|
||||
(source1: O1, _ source2: O2, _ source3: O3, _ resultSelector: (O1.E, O2.E, O3.E) throws -> R)
|
||||
-> Observable<R> {
|
||||
|
|
@ -161,6 +173,12 @@ class CombineLatest3<E1, E2, E3, R> : Producer<R> {
|
|||
|
||||
// 4
|
||||
|
||||
/**
|
||||
Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences produces an element.
|
||||
|
||||
- parameter resultSelector: Function to invoke whenever any of the sources produces an element.
|
||||
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
|
||||
*/
|
||||
public func combineLatest<O1: ObservableType, O2: ObservableType, O3: ObservableType, O4: ObservableType, R>
|
||||
(source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ resultSelector: (O1.E, O2.E, O3.E, O4.E) throws -> R)
|
||||
-> Observable<R> {
|
||||
|
|
@ -245,6 +263,12 @@ class CombineLatest4<E1, E2, E3, E4, R> : Producer<R> {
|
|||
|
||||
// 5
|
||||
|
||||
/**
|
||||
Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences produces an element.
|
||||
|
||||
- parameter resultSelector: Function to invoke whenever any of the sources produces an element.
|
||||
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
|
||||
*/
|
||||
public func combineLatest<O1: ObservableType, O2: ObservableType, O3: ObservableType, O4: ObservableType, O5: ObservableType, R>
|
||||
(source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ resultSelector: (O1.E, O2.E, O3.E, O4.E, O5.E) throws -> R)
|
||||
-> Observable<R> {
|
||||
|
|
@ -336,6 +360,12 @@ class CombineLatest5<E1, E2, E3, E4, E5, R> : Producer<R> {
|
|||
|
||||
// 6
|
||||
|
||||
/**
|
||||
Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences produces an element.
|
||||
|
||||
- parameter resultSelector: Function to invoke whenever any of the sources produces an element.
|
||||
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
|
||||
*/
|
||||
public func combineLatest<O1: ObservableType, O2: ObservableType, O3: ObservableType, O4: ObservableType, O5: ObservableType, O6: ObservableType, R>
|
||||
(source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, _ resultSelector: (O1.E, O2.E, O3.E, O4.E, O5.E, O6.E) throws -> R)
|
||||
-> Observable<R> {
|
||||
|
|
@ -434,6 +464,12 @@ class CombineLatest6<E1, E2, E3, E4, E5, E6, R> : Producer<R> {
|
|||
|
||||
// 7
|
||||
|
||||
/**
|
||||
Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences produces an element.
|
||||
|
||||
- parameter resultSelector: Function to invoke whenever any of the sources produces an element.
|
||||
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
|
||||
*/
|
||||
public func combineLatest<O1: ObservableType, O2: ObservableType, O3: ObservableType, O4: ObservableType, O5: ObservableType, O6: ObservableType, O7: ObservableType, R>
|
||||
(source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, _ source7: O7, _ resultSelector: (O1.E, O2.E, O3.E, O4.E, O5.E, O6.E, O7.E) throws -> R)
|
||||
-> Observable<R> {
|
||||
|
|
@ -539,6 +575,12 @@ class CombineLatest7<E1, E2, E3, E4, E5, E6, E7, R> : Producer<R> {
|
|||
|
||||
// 8
|
||||
|
||||
/**
|
||||
Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences produces an element.
|
||||
|
||||
- parameter resultSelector: Function to invoke whenever any of the sources produces an element.
|
||||
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
|
||||
*/
|
||||
public func combineLatest<O1: ObservableType, O2: ObservableType, O3: ObservableType, O4: ObservableType, O5: ObservableType, O6: ObservableType, O7: ObservableType, O8: ObservableType, R>
|
||||
(source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, _ source7: O7, _ source8: O8, _ resultSelector: (O1.E, O2.E, O3.E, O4.E, O5.E, O6.E, O7.E, O8.E) throws -> R)
|
||||
-> Observable<R> {
|
||||
|
|
|
|||
|
|
@ -12,24 +12,30 @@ import Foundation
|
|||
|
||||
// <%= i %>
|
||||
|
||||
public func combineLatest<<%= ", ".join(Array(1...i).map { "O\($0): ObservableType" }) %>, R>
|
||||
(<%= ", _ ".join(Array(1...i).map { "source\($0): O\($0)" }) %>, _ resultSelector: (<%= ", ".join(Array(1...i).map { "O\($0).E" }) %>) throws -> R)
|
||||
/**
|
||||
Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences produces an element.
|
||||
|
||||
- parameter resultSelector: Function to invoke whenever any of the sources produces an element.
|
||||
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
|
||||
*/
|
||||
public func combineLatest<<%= (Array(1...i).map { "O\($0): ObservableType" }).joinWithSeparator(", ") %>, R>
|
||||
(<%= (Array(1...i).map { "source\($0): O\($0)" }).joinWithSeparator(", _ ") %>, _ resultSelector: (<%= (Array(1...i).map { "O\($0).E" }).joinWithSeparator(", ") %>) throws -> R)
|
||||
-> Observable<R> {
|
||||
return CombineLatest<%= i %>(
|
||||
<%= ", ".join(Array(1...i).map { "source\($0): source\($0).asObservable()" }) %>,
|
||||
<%= (Array(1...i).map { "source\($0): source\($0).asObservable()" }).joinWithSeparator(", ") %>,
|
||||
resultSelector: resultSelector
|
||||
)
|
||||
}
|
||||
|
||||
class CombineLatestSink<%= i %>_<<%= ", ".join(Array(1...i).map { "E\($0)" }) %>, O: ObserverType> : CombineLatestSink<O> {
|
||||
class CombineLatestSink<%= i %>_<<%= (Array(1...i).map { "E\($0)" }).joinWithSeparator(", ") %>, O: ObserverType> : CombineLatestSink<O> {
|
||||
typealias R = O.E
|
||||
typealias Parent = CombineLatest<%= i %><<%= ", ".join(Array(1...i).map { "E\($0)" }) %>, R>
|
||||
typealias Parent = CombineLatest<%= i %><<%= (Array(1...i).map { "E\($0)" }).joinWithSeparator(", ") %>, R>
|
||||
|
||||
let parent: Parent
|
||||
|
||||
<%= "\n".join(Array(1...i).map {
|
||||
<%= (Array(1...i).map {
|
||||
" var latestElement\($0): E\($0)! = nil"
|
||||
}) %>
|
||||
}).joinWithSeparator("\n") %>
|
||||
|
||||
init(parent: Parent, observer: O, cancel: Disposable) {
|
||||
self.parent = parent
|
||||
|
|
@ -37,41 +43,41 @@ class CombineLatestSink<%= i %>_<<%= ", ".join(Array(1...i).map { "E\($0)" }) %>
|
|||
}
|
||||
|
||||
func run() -> Disposable {
|
||||
<%= "\n".join(Array(1...i).map {
|
||||
<%= (Array(1...i).map {
|
||||
" let subscription\($0) = SingleAssignmentDisposable()"
|
||||
}) %>
|
||||
}).joinWithSeparator("\n") %>
|
||||
|
||||
<%= "\n".join(Array(1...i).map {
|
||||
<%= (Array(1...i).map {
|
||||
" let observer\($0) = CombineLatestObserver(lock: lock, parent: self, index: \($0 - 1), setLatestValue: { (e: E\($0)) -> Void in self.latestElement\($0) = e }, this: subscription\($0))"
|
||||
}) %>
|
||||
}).joinWithSeparator("\n") %>
|
||||
|
||||
<%= "\n".join(Array(1...i).map {
|
||||
<%= (Array(1...i).map {
|
||||
" subscription\($0).disposable = parent.source\($0).subscribeSafe(observer\($0))"
|
||||
}) %>
|
||||
}).joinWithSeparator("\n") %>
|
||||
|
||||
return CompositeDisposable(disposables: [
|
||||
<%= ",\n".join(Array(1...i).map { " subscription\($0)" }) %>
|
||||
<%= (Array(1...i).map { " subscription\($0)" }).joinWithSeparator(",\n") %>
|
||||
])
|
||||
}
|
||||
|
||||
override func getResult() throws -> R {
|
||||
return try self.parent.resultSelector(<%= ", ".join(Array(1...i).map { "latestElement\($0)" }) %>)
|
||||
return try self.parent.resultSelector(<%= (Array(1...i).map { "latestElement\($0)" }).joinWithSeparator(", ") %>)
|
||||
}
|
||||
}
|
||||
|
||||
class CombineLatest<%= i %><<%= ", ".join(Array(1...i).map { "E\($0)" }) %>, R> : Producer<R> {
|
||||
typealias ResultSelector = (<%= ", ".join(Array(1...i).map { "E\($0)" }) %>) throws -> R
|
||||
class CombineLatest<%= i %><<%= (Array(1...i).map { "E\($0)" }).joinWithSeparator(", ") %>, R> : Producer<R> {
|
||||
typealias ResultSelector = (<%= (Array(1...i).map { "E\($0)" }).joinWithSeparator(", ") %>) throws -> R
|
||||
|
||||
<%= "\n".join(Array(1...i).map {
|
||||
<%= (Array(1...i).map {
|
||||
" let source\($0): Observable<E\($0)>"
|
||||
}) %>
|
||||
}).joinWithSeparator("\n") %>
|
||||
|
||||
let resultSelector: ResultSelector
|
||||
|
||||
init(<%= ", ".join(Array(1...i).map { "source\($0): Observable<E\($0)>" }) %>, resultSelector: ResultSelector) {
|
||||
<%= "\n".join(Array(1...i).map {
|
||||
init(<%= (Array(1...i).map { "source\($0): Observable<E\($0)>" }).joinWithSeparator(", ") %>, resultSelector: ResultSelector) {
|
||||
<%= (Array(1...i).map {
|
||||
" self.source\($0) = source\($0)"
|
||||
}) %>
|
||||
}).joinWithSeparator("\n") %>
|
||||
|
||||
self.resultSelector = resultSelector
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,15 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
#if TRACE_RESOURCES
|
||||
/**
|
||||
Counts number of `SerialDispatchQueueObservables`.
|
||||
|
||||
Purposed for unit tests.
|
||||
*/
|
||||
public var numberOfSerialDispatchQueueObservables: Int32 = 0
|
||||
#endif
|
||||
|
||||
class ObserveOnSerialDispatchQueueSink<O: ObserverType> : ObserverBase<O.E> {
|
||||
|
||||
let scheduler: SerialDispatchQueueScheduler
|
||||
|
|
@ -26,7 +35,7 @@ class ObserveOnSerialDispatchQueueSink<O: ObserverType> : ObserverBase<O.E> {
|
|||
|
||||
override func onCore(event: Event<E>) {
|
||||
self.scheduler.schedule(()) { (_) -> Disposable in
|
||||
send(self.observer, event)
|
||||
self.observer.on(event)
|
||||
|
||||
if event.isStopEvent {
|
||||
self.dispose()
|
||||
|
|
|
|||
|
|
@ -1,88 +0,0 @@
|
|||
//
|
||||
// ObserveSingleOn.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/15/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
let ObserveSingleOnMoreThenOneElement = "Observed sequence was expected to have more then one element, and `observeSingleOn` operator works on sequences with at most one element."
|
||||
|
||||
// This class is used to forward sequence of AT MOST ONE observed element to
|
||||
// another schedule.
|
||||
//
|
||||
// In case sequence contains more then one element, it will fire an exception.
|
||||
|
||||
class ObserveSingleOnObserver<O: ObserverType> : Sink<O>, ObserverType {
|
||||
typealias Element = O.E
|
||||
typealias Parent = ObserveSingleOn<Element>
|
||||
|
||||
let parent: Parent
|
||||
|
||||
var lastElement: Event<Element>? = nil
|
||||
|
||||
init(parent: Parent, observer: O, cancel: Disposable) {
|
||||
self.parent = parent
|
||||
super.init(observer: observer, cancel: cancel)
|
||||
}
|
||||
|
||||
func on(event: Event<Element>) {
|
||||
var elementToForward: Event<Element>?
|
||||
var stopEventToForward: Event<Element>?
|
||||
|
||||
_ = self.parent.scheduler
|
||||
|
||||
switch event {
|
||||
case .Next:
|
||||
if self.lastElement != nil {
|
||||
rxFatalError(ObserveSingleOnMoreThenOneElement)
|
||||
}
|
||||
|
||||
self.lastElement = event
|
||||
case .Error:
|
||||
if self.lastElement != nil {
|
||||
rxFatalError(ObserveSingleOnMoreThenOneElement)
|
||||
}
|
||||
stopEventToForward = event
|
||||
case .Completed:
|
||||
elementToForward = self.lastElement
|
||||
stopEventToForward = event
|
||||
}
|
||||
|
||||
if let stopEventToForward = stopEventToForward {
|
||||
self.parent.scheduler.schedule(()) { (_) in
|
||||
if let elementToForward = elementToForward {
|
||||
self.observer?.on(elementToForward)
|
||||
}
|
||||
|
||||
self.observer?.on(stopEventToForward)
|
||||
|
||||
self.dispose()
|
||||
|
||||
return NopDisposable.instance
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func run() -> Disposable {
|
||||
return self.parent.source.subscribeSafe(self)
|
||||
}
|
||||
}
|
||||
|
||||
class ObserveSingleOn<Element> : Producer<Element> {
|
||||
let scheduler: ImmediateScheduler
|
||||
let source: Observable<Element>
|
||||
|
||||
init(source: Observable<Element>, scheduler: ImmediateScheduler) {
|
||||
self.source = source
|
||||
self.scheduler = scheduler
|
||||
}
|
||||
|
||||
override func run<O: ObserverType where O.E == Element>(observer: O, cancel: Disposable, setSink: (Disposable) -> Void) -> Disposable {
|
||||
let sink = ObserveSingleOnObserver(parent: self, observer: observer, cancel: cancel)
|
||||
setSink(sink)
|
||||
return sink.run()
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,12 @@ import Foundation
|
|||
|
||||
// 2
|
||||
|
||||
/**
|
||||
Merges the specified observable sequences into one observable sequence by using the selector function whenever all of the observable sequences have produced an element at a corresponding index.
|
||||
|
||||
- parameter resultSelector: Function to invoke for each series of elements at corresponding indexes in the sources.
|
||||
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
|
||||
*/
|
||||
public func zip<O1: ObservableType, O2: ObservableType, R>
|
||||
(source1: O1, _ source2: O2, _ resultSelector: (O1.E, O2.E) throws -> R)
|
||||
-> Observable<R> {
|
||||
|
|
@ -96,6 +102,12 @@ class Zip2<E1, E2, R> : Producer<R> {
|
|||
|
||||
// 3
|
||||
|
||||
/**
|
||||
Merges the specified observable sequences into one observable sequence by using the selector function whenever all of the observable sequences have produced an element at a corresponding index.
|
||||
|
||||
- parameter resultSelector: Function to invoke for each series of elements at corresponding indexes in the sources.
|
||||
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
|
||||
*/
|
||||
public func zip<O1: ObservableType, O2: ObservableType, O3: ObservableType, R>
|
||||
(source1: O1, _ source2: O2, _ source3: O3, _ resultSelector: (O1.E, O2.E, O3.E) throws -> R)
|
||||
-> Observable<R> {
|
||||
|
|
@ -186,6 +198,12 @@ class Zip3<E1, E2, E3, R> : Producer<R> {
|
|||
|
||||
// 4
|
||||
|
||||
/**
|
||||
Merges the specified observable sequences into one observable sequence by using the selector function whenever all of the observable sequences have produced an element at a corresponding index.
|
||||
|
||||
- parameter resultSelector: Function to invoke for each series of elements at corresponding indexes in the sources.
|
||||
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
|
||||
*/
|
||||
public func zip<O1: ObservableType, O2: ObservableType, O3: ObservableType, O4: ObservableType, R>
|
||||
(source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ resultSelector: (O1.E, O2.E, O3.E, O4.E) throws -> R)
|
||||
-> Observable<R> {
|
||||
|
|
@ -284,6 +302,12 @@ class Zip4<E1, E2, E3, E4, R> : Producer<R> {
|
|||
|
||||
// 5
|
||||
|
||||
/**
|
||||
Merges the specified observable sequences into one observable sequence by using the selector function whenever all of the observable sequences have produced an element at a corresponding index.
|
||||
|
||||
- parameter resultSelector: Function to invoke for each series of elements at corresponding indexes in the sources.
|
||||
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
|
||||
*/
|
||||
public func zip<O1: ObservableType, O2: ObservableType, O3: ObservableType, O4: ObservableType, O5: ObservableType, R>
|
||||
(source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ resultSelector: (O1.E, O2.E, O3.E, O4.E, O5.E) throws -> R)
|
||||
-> Observable<R> {
|
||||
|
|
@ -390,6 +414,12 @@ class Zip5<E1, E2, E3, E4, E5, R> : Producer<R> {
|
|||
|
||||
// 6
|
||||
|
||||
/**
|
||||
Merges the specified observable sequences into one observable sequence by using the selector function whenever all of the observable sequences have produced an element at a corresponding index.
|
||||
|
||||
- parameter resultSelector: Function to invoke for each series of elements at corresponding indexes in the sources.
|
||||
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
|
||||
*/
|
||||
public func zip<O1: ObservableType, O2: ObservableType, O3: ObservableType, O4: ObservableType, O5: ObservableType, O6: ObservableType, R>
|
||||
(source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, _ resultSelector: (O1.E, O2.E, O3.E, O4.E, O5.E, O6.E) throws -> R)
|
||||
-> Observable<R> {
|
||||
|
|
@ -504,6 +534,12 @@ class Zip6<E1, E2, E3, E4, E5, E6, R> : Producer<R> {
|
|||
|
||||
// 7
|
||||
|
||||
/**
|
||||
Merges the specified observable sequences into one observable sequence by using the selector function whenever all of the observable sequences have produced an element at a corresponding index.
|
||||
|
||||
- parameter resultSelector: Function to invoke for each series of elements at corresponding indexes in the sources.
|
||||
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
|
||||
*/
|
||||
public func zip<O1: ObservableType, O2: ObservableType, O3: ObservableType, O4: ObservableType, O5: ObservableType, O6: ObservableType, O7: ObservableType, R>
|
||||
(source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, _ source7: O7, _ resultSelector: (O1.E, O2.E, O3.E, O4.E, O5.E, O6.E, O7.E) throws -> R)
|
||||
-> Observable<R> {
|
||||
|
|
@ -626,6 +662,12 @@ class Zip7<E1, E2, E3, E4, E5, E6, E7, R> : Producer<R> {
|
|||
|
||||
// 8
|
||||
|
||||
/**
|
||||
Merges the specified observable sequences into one observable sequence by using the selector function whenever all of the observable sequences have produced an element at a corresponding index.
|
||||
|
||||
- parameter resultSelector: Function to invoke for each series of elements at corresponding indexes in the sources.
|
||||
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
|
||||
*/
|
||||
public func zip<O1: ObservableType, O2: ObservableType, O3: ObservableType, O4: ObservableType, O5: ObservableType, O6: ObservableType, O7: ObservableType, O8: ObservableType, R>
|
||||
(source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, _ source7: O7, _ source8: O8, _ resultSelector: (O1.E, O2.E, O3.E, O4.E, O5.E, O6.E, O7.E, O8.E) throws -> R)
|
||||
-> Observable<R> {
|
||||
|
|
|
|||
|
|
@ -12,24 +12,30 @@ import Foundation
|
|||
|
||||
// <%= i %>
|
||||
|
||||
public func zip<<%= ", ".join(Array(1...i).map { "O\($0): ObservableType" }) %>, R>
|
||||
(<%= ", _ ".join(Array(1...i).map { "source\($0): O\($0)" }) %>, _ resultSelector: (<%= ", ".join(Array(1...i).map { "O\($0).E" }) %>) throws -> R)
|
||||
/**
|
||||
Merges the specified observable sequences into one observable sequence by using the selector function whenever all of the observable sequences have produced an element at a corresponding index.
|
||||
|
||||
- parameter resultSelector: Function to invoke for each series of elements at corresponding indexes in the sources.
|
||||
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
|
||||
*/
|
||||
public func zip<<%= (Array(1...i).map { "O\($0): ObservableType" }).joinWithSeparator(", ") %>, R>
|
||||
(<%= (Array(1...i).map { "source\($0): O\($0)" }).joinWithSeparator(", _ ") %>, _ resultSelector: (<%= (Array(1...i).map { "O\($0).E" }).joinWithSeparator(", ") %>) throws -> R)
|
||||
-> Observable<R> {
|
||||
return Zip<%= i %>(
|
||||
<%= ", ".join(Array(1...i).map { "source\($0): source\($0).asObservable()" }) %>,
|
||||
<%= (Array(1...i).map { "source\($0): source\($0).asObservable()" }).joinWithSeparator(", ") %>,
|
||||
resultSelector: resultSelector
|
||||
)
|
||||
}
|
||||
|
||||
class ZipSink<%= i %>_<<%= ", ".join(Array(1...i).map { "E\($0)" }) %>, O: ObserverType> : ZipSink<O> {
|
||||
class ZipSink<%= i %>_<<%= (Array(1...i).map { "E\($0)" }).joinWithSeparator(", ") %>, O: ObserverType> : ZipSink<O> {
|
||||
typealias R = O.E
|
||||
typealias Parent = Zip<%= i %><<%= ", ".join(Array(1...i).map { "E\($0)" }) %>, R>
|
||||
typealias Parent = Zip<%= i %><<%= (Array(1...i).map { "E\($0)" }).joinWithSeparator(", ") %>, R>
|
||||
|
||||
let parent: Parent
|
||||
|
||||
<%= "\n".join(Array(1...i).map {
|
||||
<%= (Array(1...i).map {
|
||||
" var values\($0): Queue<E\($0)> = Queue(capacity: 2)"
|
||||
}) %>
|
||||
}).joinWithSeparator("\n") %>
|
||||
|
||||
init(parent: Parent, observer: O, cancel: Disposable) {
|
||||
self.parent = parent
|
||||
|
|
@ -38,9 +44,9 @@ class ZipSink<%= i %>_<<%= ", ".join(Array(1...i).map { "E\($0)" }) %>, O: Obser
|
|||
|
||||
override func hasElements(index: Int) -> Bool {
|
||||
switch (index) {
|
||||
<%= "".join(Array(0..<i).map {
|
||||
<%= (Array(0..<i).map {
|
||||
" case \($0): return values\($0 + 1).count > 0\n"
|
||||
}) %>
|
||||
}).joinWithSeparator("") %>
|
||||
default:
|
||||
rxFatalError("Unhandled case \(index)")
|
||||
}
|
||||
|
|
@ -49,38 +55,38 @@ class ZipSink<%= i %>_<<%= ", ".join(Array(1...i).map { "E\($0)" }) %>, O: Obser
|
|||
}
|
||||
|
||||
func run() -> Disposable {
|
||||
<%= "\n".join(Array(1...i).map {
|
||||
<%= (Array(1...i).map {
|
||||
" let subscription\($0) = SingleAssignmentDisposable()"
|
||||
}) %>
|
||||
}).joinWithSeparator("\n") %>
|
||||
|
||||
<%= "\n".join(Array(1...i).map {
|
||||
<%= (Array(1...i).map {
|
||||
" let observer\($0) = ZipObserver(lock: lock, parent: self, index: \($0 - 1), setNextValue: { self.values\($0).enqueue($0) }, this: subscription\($0))"
|
||||
}) %>
|
||||
}).joinWithSeparator("\n") %>
|
||||
|
||||
<%= "\n".join(Array(1...i).map {
|
||||
" subscription\($0).disposable = parent.source\($0).subscribeSafe(observer\($0))" })
|
||||
<%= (Array(1...i).map {
|
||||
" subscription\($0).disposable = parent.source\($0).subscribeSafe(observer\($0))" }).joinWithSeparator("\n")
|
||||
%>
|
||||
|
||||
return CompositeDisposable(disposables: [
|
||||
<%= ",\n".join(Array(1...i).map { " subscription\($0)" }) %>
|
||||
<%= (Array(1...i).map { " subscription\($0)" }).joinWithSeparator(",\n") %>
|
||||
])
|
||||
}
|
||||
|
||||
override func getResult() throws -> R {
|
||||
return try self.parent.resultSelector(<%= ", ".join(Array(1...i).map { "values\($0).dequeue()" }) %>)
|
||||
return try self.parent.resultSelector(<%= (Array(1...i).map { "values\($0).dequeue()" }).joinWithSeparator(", ") %>)
|
||||
}
|
||||
}
|
||||
|
||||
class Zip<%= i %><<%= ", ".join(Array(1...i).map { "E\($0)" }) %>, R> : Producer<R> {
|
||||
typealias ResultSelector = (<%= ", ".join(Array(1...i).map { "E\($0)" }) %>) throws -> R
|
||||
class Zip<%= i %><<%= (Array(1...i).map { "E\($0)" }).joinWithSeparator(", ") %>, R> : Producer<R> {
|
||||
typealias ResultSelector = (<%= (Array(1...i).map { "E\($0)" }).joinWithSeparator(", ") %>) throws -> R
|
||||
|
||||
<%= "\n".join(Array(1...i).map { " let source\($0): Observable<E\($0)>" }) %>
|
||||
<%= (Array(1...i).map { " let source\($0): Observable<E\($0)>" }).joinWithSeparator("\n") %>
|
||||
|
||||
let resultSelector: ResultSelector
|
||||
|
||||
init(<%= ", ".join(Array(1...i).map { "source\($0): Observable<E\($0)>" }) %>, resultSelector: ResultSelector) {
|
||||
<%= "\n".join(Array(1...i).map {
|
||||
" self.source\($0) = source\($0)" })
|
||||
init(<%= (Array(1...i).map { "source\($0): Observable<E\($0)>" }).joinWithSeparator(", ") %>, resultSelector: ResultSelector) {
|
||||
<%= (Array(1...i).map {
|
||||
" self.source\($0) = source\($0)" }).joinWithSeparator("\n")
|
||||
%>
|
||||
|
||||
self.resultSelector = resultSelector
|
||||
|
|
|
|||
|
|
@ -11,11 +11,31 @@ import Foundation
|
|||
// reduce
|
||||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Applies an `accumulator` function over an observable sequence, returning the result of the aggregation as a single element in the result sequence. The specified `seed` value is used as the initial accumulator value.
|
||||
|
||||
For aggregation behavior with incremental intermediate results, see `scan`.
|
||||
|
||||
- parameter seed: The initial accumulator value.
|
||||
- parameter accumulator: A accumulator function to be invoked on each element.
|
||||
- parameter mapResult: A function to transform the final accumulator value into the result value.
|
||||
- returns: An observable sequence containing a single element with the final accumulator value.
|
||||
*/
|
||||
public func reduce<A, R>(seed: A, _ accumulator: (A, E) throws -> A, mapResult: (A) throws -> R)
|
||||
-> Observable<R> {
|
||||
return Reduce(source: self.asObservable(), seed: seed, accumulator: accumulator, mapResult: mapResult)
|
||||
}
|
||||
|
||||
/**
|
||||
Applies an `accumulator` function over an observable sequence, returning the result of the aggregation as a single element in the result sequence. The specified `seed` value is used as the initial accumulator value.
|
||||
|
||||
For aggregation behavior with incremental intermediate results, see `scan`.
|
||||
|
||||
- parameter seed: The initial accumulator value.
|
||||
- parameter accumulator: A accumulator function to be invoked on each element.
|
||||
- returns: An observable sequence containing a single element with the final accumulator value.
|
||||
*/
|
||||
public func reduce<A>(seed: A, _ accumulator: (A, E) throws -> A)
|
||||
-> Observable<A> {
|
||||
return Reduce(source: self.asObservable(), seed: seed, accumulator: accumulator, mapResult: { $0 })
|
||||
|
|
|
|||
|
|
@ -11,11 +11,33 @@ import Foundation
|
|||
// multicast
|
||||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Multicasts the source sequence notifications through the specified subject to the resulting connectable observable.
|
||||
|
||||
Upon connection of the connectable observable, the subject is subscribed to the source exactly one, and messages are forwarded to the observers registered with the connectable observable.
|
||||
|
||||
For specializations with fixed subject types, see `publish` and `replay`.
|
||||
|
||||
- parameter subject: Subject to push source elements into.
|
||||
- returns: A connectable observable sequence that upon connection causes the source sequence to push results into the specified subject.
|
||||
*/
|
||||
public func multicast<S: SubjectType where S.SubjectObserverType.E == E>(subject: S)
|
||||
-> ConnectableObservable<S> {
|
||||
return ConnectableObservable(source: self.asObservable(), subject: subject)
|
||||
}
|
||||
|
||||
/**
|
||||
Multicasts the source sequence notifications through an instantiated subject into all uses of the sequence within a selector function.
|
||||
|
||||
Each subscription to the resulting sequence causes a separate multicast invocation, exposing the sequence resulting from the selector function's invocation.
|
||||
|
||||
For specializations with fixed subject types, see `publish` and `replay`.
|
||||
|
||||
- parameter subjectSelector: Factory function to create an intermediate subject through which the source sequence's elements will be multicast to the selector function.
|
||||
- parameter selector: Selector function which can use the multicasted source sequence subject to the policies enforced by the created subject.
|
||||
- returns: An observable sequence that contains the elements of a sequence produced by multicasting the source sequence within a selector function.
|
||||
*/
|
||||
public func multicast<S: SubjectType, R where S.SubjectObserverType.E == E>(subjectSelector: () throws -> S, selector: (Observable<S.E>) throws -> Observable<R>)
|
||||
-> Observable<R> {
|
||||
return Multicast(
|
||||
|
|
@ -29,6 +51,14 @@ extension ObservableType {
|
|||
// publish
|
||||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Returns a connectable observable sequence that shares a single subscription to the underlying sequence.
|
||||
|
||||
This operator is a specialization of `multicast` using a `PublishSubject`.
|
||||
|
||||
- returns: A connectable observable sequence that shares a single subscription to the underlying sequence.
|
||||
*/
|
||||
public func publish() -> ConnectableObservable<PublishSubject<E>> {
|
||||
return self.multicast(PublishSubject())
|
||||
}
|
||||
|
|
@ -37,6 +67,15 @@ extension ObservableType {
|
|||
// replay
|
||||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Returns a connectable observable sequence that shares a single subscription to the underlying sequence replaying bufferSize elements.
|
||||
|
||||
This operator is a specialization of `multicast` using a `ReplaySubject`.
|
||||
|
||||
- parameter bufferSize: Maximum element count of the replay buffer.
|
||||
- returns: A connectable observable sequence that shares a single subscription to the underlying sequence.
|
||||
*/
|
||||
public func replay(bufferSize: Int)
|
||||
-> ConnectableObservable<ReplaySubject<E>> {
|
||||
return self.multicast(ReplaySubject.create(bufferSize: bufferSize))
|
||||
|
|
@ -46,6 +85,12 @@ extension ObservableType {
|
|||
// refcount
|
||||
|
||||
extension ConnectableObservableType {
|
||||
|
||||
/**
|
||||
Returns an observable sequence that stays connected to the source as long as there is at least one subscription to the observable sequence.
|
||||
|
||||
- returns: An observable sequence that stays connected to the source as long as there is at least one subscription to the observable sequence.
|
||||
*/
|
||||
public func refCount() -> Observable<E> {
|
||||
return RefCount(source: self)
|
||||
}
|
||||
|
|
@ -54,6 +99,14 @@ extension ConnectableObservableType {
|
|||
// share
|
||||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Returns an observable sequence that shares a single subscription to the underlying sequence.
|
||||
|
||||
This operator is a specialization of publish which creates a subscription when the number of observers goes from zero to one, then shares that subscription with all subsequent observers until the number of observers returns to zero, at which point the subscription is disposed.
|
||||
|
||||
- returns: An observable sequence that contains the elements of a sequence produced by multicasting the source sequence.
|
||||
*/
|
||||
public func share() -> Observable<E> {
|
||||
return self.publish().refCount()
|
||||
}
|
||||
|
|
@ -62,6 +115,15 @@ extension ObservableType {
|
|||
// shareReplay
|
||||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Returns an observable sequence that shares a single subscription to the underlying sequence replaying notifications subject to a maximum time length for the replay buffer.
|
||||
|
||||
This operator is a specialization of replay which creates a subscription when the number of observers goes from zero to one, then shares that subscription with all subsequent observers until the number of observers returns to zero, at which point the subscription is disposed.
|
||||
|
||||
- parameter bufferSize: Maximum element count of the replay buffer.
|
||||
- returns: An observable sequence that contains the elements of a sequence produced by multicasting the source sequence.
|
||||
*/
|
||||
public func shareReplay(bufferSize: Int)
|
||||
-> Observable<E> {
|
||||
return self.replay(bufferSize).refCount()
|
||||
|
|
|
|||
|
|
@ -8,26 +8,19 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
// observeOnSingle
|
||||
|
||||
extension ObservableType {
|
||||
// `observeSingleOn` assumes that observed sequence will have one element
|
||||
// and in cases it has more than one element it will throw an exception.
|
||||
//
|
||||
// Most common use case for `observeSingleOn` would be to execute some work on background thread
|
||||
// and return result to main thread.
|
||||
//
|
||||
// This is a performance gain considering general case.
|
||||
public func observeSingleOn(scheduler: ImmediateScheduler)
|
||||
-> Observable<E> {
|
||||
return ObserveSingleOn(source: self.asObservable(), scheduler: scheduler)
|
||||
}
|
||||
}
|
||||
|
||||
// observeOn
|
||||
|
||||
extension ObservableType {
|
||||
|
||||
|
||||
/**
|
||||
Wraps the source sequence in order to run its observer callbacks on the specified scheduler.
|
||||
|
||||
This only invokes observer callbacks on a `scheduler`. In case the subscription and/or unsubscription
|
||||
actions have side-effects that require to be run on a scheduler, use `subscribeOn`.
|
||||
|
||||
- parameter scheduler: Scheduler to notify observers on.
|
||||
- returns: The source sequence whose observations happen on the specified scheduler.
|
||||
*/
|
||||
public func observeOn(scheduler: ImmediateScheduler)
|
||||
-> Observable<E> {
|
||||
if let scheduler = scheduler as? SerialDispatchQueueScheduler {
|
||||
|
|
@ -42,6 +35,20 @@ extension ObservableType {
|
|||
// subscribeOn
|
||||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Wraps the source sequence in order to run its subscription and unsubscription logic on the specified
|
||||
scheduler.
|
||||
|
||||
This operation is not commonly used.
|
||||
|
||||
This only performs the side-effects of subscription and unsubscription on the specified scheduler.
|
||||
|
||||
In order to invoke observer callbacks on a `scheduler`, use `observeOn`.
|
||||
|
||||
- parameter scheduler: Scheduler to perform subscription and unsubscription actions on.
|
||||
- returns: The source sequence whose subscriptions and unsubscriptions happen on the specified scheduler.
|
||||
*/
|
||||
public func subscribeOn(scheduler: ImmediateScheduler)
|
||||
-> Observable<E> {
|
||||
return SubscribeOn(source: self.asObservable(), scheduler: scheduler)
|
||||
|
|
|
|||
|
|
@ -10,28 +10,57 @@ import Foundation
|
|||
|
||||
// create
|
||||
|
||||
/**
|
||||
Creates an observable sequence from a specified subscribe method implementation.
|
||||
|
||||
- parameter subscribe: Implementation of the resulting observable sequence's `subscribe` method.
|
||||
- returns: The observable sequence with the specified implementation for the `subscribe` method.
|
||||
*/
|
||||
public func create<E>(subscribe: (ObserverOf<E>) -> Disposable) -> Observable<E> {
|
||||
return AnonymousObservable(subscribe)
|
||||
}
|
||||
|
||||
// empty
|
||||
|
||||
/**
|
||||
Returns an empty observable sequence, using the specified scheduler to send out the single `Completed` message.
|
||||
|
||||
- returns: An observable sequence with no elements.
|
||||
*/
|
||||
public func empty<E>() -> Observable<E> {
|
||||
return Empty<E>()
|
||||
}
|
||||
|
||||
// never
|
||||
|
||||
/**
|
||||
Returns a non-terminating observable sequence, which can be used to denote an infinite duration.
|
||||
|
||||
- returns: An observable sequence whose observers will never get called.
|
||||
*/
|
||||
public func never<E>() -> Observable<E> {
|
||||
return Never()
|
||||
}
|
||||
|
||||
// return
|
||||
// just
|
||||
|
||||
/**
|
||||
Returns an observable sequence that contains a single element.
|
||||
|
||||
- parameter element: Single element in the resulting observable sequence.
|
||||
- returns: An observable sequence containing the single specified element.
|
||||
*/
|
||||
public func just<E>(element: E) -> Observable<E> {
|
||||
return Just(element: element)
|
||||
}
|
||||
|
||||
// of
|
||||
|
||||
/**
|
||||
This method creates a new Observable instance with a variable number of elements.
|
||||
|
||||
- returns: The observable sequence whose elements are pulled from the given arguments.
|
||||
*/
|
||||
public func sequenceOf<E>(elements: E ...) -> Observable<E> {
|
||||
return AnonymousObservable { observer in
|
||||
for element in elements {
|
||||
|
|
@ -43,25 +72,44 @@ public func sequenceOf<E>(elements: E ...) -> Observable<E> {
|
|||
}
|
||||
}
|
||||
|
||||
public func from<E, S where S: SequenceType, S.Generator.Element == E>(sequence: S) -> Observable<E> {
|
||||
return AnonymousObservable { observer in
|
||||
for element in sequence {
|
||||
observer.on(.Next(element))
|
||||
|
||||
extension SequenceType {
|
||||
/**
|
||||
Converts a sequence to an observable sequence.
|
||||
|
||||
- returns: The observable sequence whose elements are pulled from the given enumerable sequence.
|
||||
*/
|
||||
public func asObservable() -> Observable<Generator.Element> {
|
||||
return AnonymousObservable { observer in
|
||||
for element in self {
|
||||
observer.on(.Next(element))
|
||||
}
|
||||
|
||||
observer.on(.Completed)
|
||||
return NopDisposable.instance
|
||||
}
|
||||
|
||||
observer.on(.Completed)
|
||||
return NopDisposable.instance
|
||||
}
|
||||
}
|
||||
|
||||
// fail
|
||||
|
||||
/**
|
||||
Returns an observable sequence that terminates with an `error`.
|
||||
|
||||
- returns: The observable sequence that terminates with specified error.
|
||||
*/
|
||||
public func failWith<E>(error: ErrorType) -> Observable<E> {
|
||||
return FailWith(error: error)
|
||||
}
|
||||
|
||||
// defer
|
||||
|
||||
/**
|
||||
Returns an observable sequence that invokes the specified factory function whenever a new observer subscribes.
|
||||
|
||||
- parameter observableFactory: Observable factory function to invoke for each observer that subscribes to the resulting sequence.
|
||||
- returns: An observable sequence whose observers trigger an invocation of the given observable factory function.
|
||||
*/
|
||||
public func deferred<E>(observableFactory: () throws -> Observable<E>)
|
||||
-> Observable<E> {
|
||||
return Deferred(observableFactory: observableFactory)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,13 @@ import Foundation
|
|||
// debug
|
||||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Prints received events for all observers on standard output.
|
||||
|
||||
- parameter identifier: Identifier that is printed together with event description to standard output.
|
||||
- returns: An observable sequence whose events are printed to standard output.
|
||||
*/
|
||||
public func debug(identifier: String = "\(__FILE__):\(__LINE__)")
|
||||
-> Observable<E> {
|
||||
return Debug(source: self.asObservable(), identifier: identifier)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,13 @@ import Foundation
|
|||
// combineLatest
|
||||
|
||||
extension CollectionType where Generator.Element : ObservableType {
|
||||
|
||||
/**
|
||||
Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences produces an element.
|
||||
|
||||
- parameter resultSelector: Function to invoke whenever any of the sources produces an element.
|
||||
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
|
||||
*/
|
||||
public func combineLatest<R>(resultSelector: [Generator.Element.E] throws -> R) -> Observable<R> {
|
||||
return CombineLatestCollectionType(sources: self, resultSelector: resultSelector)
|
||||
}
|
||||
|
|
@ -19,6 +26,13 @@ extension CollectionType where Generator.Element : ObservableType {
|
|||
// zip
|
||||
|
||||
extension CollectionType where Generator.Element : ObservableType {
|
||||
|
||||
/**
|
||||
Merges the specified observable sequences into one observable sequence by using the selector function whenever all of the observable sequences have produced an element at a corresponding index.
|
||||
|
||||
- parameter resultSelector: Function to invoke for each series of elements at corresponding indexes in the sources.
|
||||
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
|
||||
*/
|
||||
public func zip<R>(resultSelector: [Generator.Element.E] throws -> R) -> Observable<R> {
|
||||
return ZipCollectionType(sources: self, resultSelector: resultSelector)
|
||||
}
|
||||
|
|
@ -27,6 +41,17 @@ extension CollectionType where Generator.Element : ObservableType {
|
|||
// switch
|
||||
|
||||
extension ObservableType where E : ObservableType {
|
||||
|
||||
/**
|
||||
Transforms an observable sequence of observable sequences into an observable sequence
|
||||
producing values only from the most recent observable sequence.
|
||||
|
||||
Each time a new inner observable sequence is received, unsubscribe from the
|
||||
previous inner observable sequence.
|
||||
|
||||
- returns: The observable sequence that at any point in time produces the elements of the most recent inner observable sequence that has been received.
|
||||
*/
|
||||
|
||||
public func switchLatest() -> Observable<E.E> {
|
||||
return Switch(sources: self.asObservable())
|
||||
}
|
||||
|
|
@ -35,6 +60,12 @@ extension ObservableType where E : ObservableType {
|
|||
// concat
|
||||
|
||||
extension SequenceType where Generator.Element : ObservableType {
|
||||
|
||||
/**
|
||||
Concatenates all observable sequences in the given sequence, as long as the previous observable sequence terminated successfully.
|
||||
|
||||
- returns: An observable sequence that contains the elements of each given sequence, in sequential order.
|
||||
*/
|
||||
public func concat()
|
||||
-> Observable<Generator.Element.E> {
|
||||
return Concat(sources: self)
|
||||
|
|
@ -42,6 +73,12 @@ extension SequenceType where Generator.Element : ObservableType {
|
|||
}
|
||||
|
||||
extension ObservableType where E : ObservableType {
|
||||
|
||||
/**
|
||||
Concatenates all inner observable sequences, as long as the previous observable sequence terminated successfully.
|
||||
|
||||
- returns: An observable sequence that contains the elements of each observed inner sequence, in sequential order.
|
||||
*/
|
||||
public func concat() -> Observable<E.E> {
|
||||
return self.merge(maxConcurrent: 1)
|
||||
}
|
||||
|
|
@ -50,10 +87,22 @@ extension ObservableType where E : ObservableType {
|
|||
// merge
|
||||
|
||||
extension ObservableType where E : ObservableType {
|
||||
|
||||
/**
|
||||
Merges elements from all observable sequences in the given enumerable sequence into a single observable sequence.
|
||||
|
||||
- parameter maxConcurrent: Maximum number of inner observable sequences being subscribed to concurrently.
|
||||
- returns: The observable sequence that merges the elements of the observable sequences.
|
||||
*/
|
||||
public func merge() -> Observable<E.E> {
|
||||
return Merge(sources: self.asObservable(), maxConcurrent: 0)
|
||||
}
|
||||
|
||||
/**
|
||||
Merges elements from all inner observable sequences into a single observable sequence, limiting the number of concurrent subscriptions to inner sequences.
|
||||
|
||||
- returns: The observable sequence that merges the elements of the inner sequences.
|
||||
*/
|
||||
public func merge(maxConcurrent maxConcurrent: Int)
|
||||
-> Observable<E.E> {
|
||||
return Merge(sources: self.asObservable(), maxConcurrent: maxConcurrent)
|
||||
|
|
@ -63,25 +112,37 @@ extension ObservableType where E : ObservableType {
|
|||
// catch
|
||||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Continues an observable sequence that is terminated by an error with the observable sequence produced by the handler.
|
||||
|
||||
- parameter handler: Error handler function, producing another observable sequence.
|
||||
- returns: An observable sequence containing the source sequence's elements, followed by the elements produced by the handler's resulting observable sequence in case an error occurred.
|
||||
*/
|
||||
public func catchError(handler: (ErrorType) throws -> Observable<E>)
|
||||
-> Observable<E> {
|
||||
return Catch(source: self.asObservable(), handler: handler)
|
||||
}
|
||||
|
||||
// In case of error sends `errorElementValue` and completes sequence
|
||||
public func catchErrorResumeNext(errorElementValue: E)
|
||||
/**
|
||||
Continues an observable sequence that is terminated by an error with a single element.
|
||||
|
||||
- parameter element: Last element in an observable sequence in case error occurs.
|
||||
- returns: An observable sequence containing the source sequence's elements, followed by the `element` in case an error occurred.
|
||||
*/
|
||||
public func catchErrorJustReturn(element: E)
|
||||
-> Observable<E> {
|
||||
return Catch(source: self.asObservable(), handler: { _ in just(errorElementValue) })
|
||||
return Catch(source: self.asObservable(), handler: { _ in just(element) })
|
||||
}
|
||||
|
||||
// When error happens `error` will be forwarded as a next `Result<E>` value
|
||||
// and sequence will be completed.
|
||||
public var catchErrorToResult: Observable <RxResult<E>> {
|
||||
return CatchToResult(source: self.asObservable())
|
||||
}
|
||||
}
|
||||
|
||||
extension SequenceType where Generator.Element : ObservableType {
|
||||
/**
|
||||
Continues an observable sequence that is terminated by an error with the next observable sequence.
|
||||
|
||||
- returns: An observable sequence containing elements from consecutive source sequences until a source sequence terminates successfully.
|
||||
*/
|
||||
public func catchError()
|
||||
-> Observable<Generator.Element.E> {
|
||||
return CatchSequence(sources: self)
|
||||
|
|
@ -91,6 +152,13 @@ extension SequenceType where Generator.Element : ObservableType {
|
|||
// takeUntil
|
||||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Returns the elements from the source observable sequence until the other observable sequence produces an element.
|
||||
|
||||
- parameter other: Observable sequence that terminates propagation of elements of the source sequence.
|
||||
- returns: An observable sequence containing the elements of the source sequence up to the point the other sequence interrupted further propagation.
|
||||
*/
|
||||
public func takeUntil<O: ObservableType>(other: O)
|
||||
-> Observable<E> {
|
||||
return TakeUntil(source: self.asObservable(), other: other.asObservable())
|
||||
|
|
@ -100,6 +168,13 @@ extension ObservableType {
|
|||
// amb
|
||||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Propagates the observable sequence that reacts first.
|
||||
|
||||
- parameter right: Second observable sequence.
|
||||
- returns: An observable sequence that surfaces either of the given sequences, whichever reacted first.
|
||||
*/
|
||||
public func amb<O2: ObservableType where O2.E == E>
|
||||
(right: O2)
|
||||
-> Observable<E> {
|
||||
|
|
@ -108,6 +183,12 @@ extension ObservableType {
|
|||
}
|
||||
|
||||
extension SequenceType where Generator.Element : ObservableType {
|
||||
|
||||
/**
|
||||
Propagates the observable sequence that reacts first.
|
||||
|
||||
- returns: An observable sequence that surfaces any of the given sequences, whichever reacted first.
|
||||
*/
|
||||
public func amb()
|
||||
-> Observable<Generator.Element.E> {
|
||||
return self.reduce(never()) { a, o in
|
||||
|
|
|
|||
|
|
@ -11,6 +11,12 @@ import Foundation
|
|||
// distinct until changed
|
||||
|
||||
extension ObservableType where E: Equatable {
|
||||
|
||||
/**
|
||||
Returns an observable sequence that contains only distinct contiguous elements according to equality operator.
|
||||
|
||||
- returns: An observable sequence only containing the distinct contiguous elements, based on equality operator, from the source sequence.
|
||||
*/
|
||||
public func distinctUntilChanged()
|
||||
-> Observable<E> {
|
||||
return self.distinctUntilChanged({ $0 }, comparer: { ($0 == $1) })
|
||||
|
|
@ -18,16 +24,35 @@ extension ObservableType where E: Equatable {
|
|||
}
|
||||
|
||||
extension ObservableType {
|
||||
/**
|
||||
Returns an observable sequence that contains only distinct contiguous elements according to the `keySelector`.
|
||||
|
||||
- parameter keySelector: A function to compute the comparison key for each element.
|
||||
- returns: An observable sequence only containing the distinct contiguous elements, based on a computed key value, from the source sequence.
|
||||
*/
|
||||
public func distinctUntilChanged<K: Equatable>(keySelector: (E) throws -> K)
|
||||
-> Observable<E> {
|
||||
return self.distinctUntilChanged(keySelector, comparer: { $0 == $1 })
|
||||
}
|
||||
|
||||
/**
|
||||
Returns an observable sequence that contains only distinct contiguous elements according to the `comparer`.
|
||||
|
||||
- parameter comparer: Equality comparer for computed key values.
|
||||
- returns: An observable sequence only containing the distinct contiguous elements, based on `comparer`, from the source sequence.
|
||||
*/
|
||||
public func distinctUntilChanged(comparer: (lhs: E, rhs: E) throws -> Bool)
|
||||
-> Observable<E> {
|
||||
return self.distinctUntilChanged({ $0 }, comparer: comparer)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Returns an observable sequence that contains only distinct contiguous elements according to the keySelector and the comparer.
|
||||
|
||||
- parameter keySelector: A function to compute the comparison key for each element.
|
||||
- parameter comparer: Equality comparer for computed key values.
|
||||
- returns: An observable sequence only containing the distinct contiguous elements, based on a computed key value and the comparer, from the source sequence.
|
||||
*/
|
||||
public func distinctUntilChanged<K>(keySelector: (E) throws -> K, comparer: (lhs: K, rhs: K) throws -> Bool)
|
||||
-> Observable<E> {
|
||||
return DistinctUntilChanged(source: self.asObservable(), selector: keySelector, comparer: comparer)
|
||||
|
|
@ -37,12 +62,27 @@ extension ObservableType {
|
|||
// do
|
||||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Invokes an action for each event in the observable sequence, and propagates all observer messages through the result sequence.
|
||||
|
||||
- parameter eventHandler: Action to invoke for each event in the observable sequence.
|
||||
- returns: The source sequence with the side-effecting behavior applied.
|
||||
*/
|
||||
public func doOn(eventHandler: (Event<E>) throws -> Void)
|
||||
-> Observable<E> {
|
||||
return Do(source: self.asObservable(), eventHandler: eventHandler)
|
||||
}
|
||||
|
||||
public func doOn(next next: (E throws -> Void)? = nil, error: (ErrorType throws -> Void)? = nil, completed: (() throws -> Void)? = nil, disposed: (() throws -> Void)? = nil)
|
||||
/**
|
||||
Invokes an action for each event in the observable sequence, and propagates all observer messages through the result sequence.
|
||||
|
||||
- parameter next: Action to invoke for each element in the observable sequence.
|
||||
- parameter error: Action to invoke upon errored termination of the observable sequence.
|
||||
- parameter completed: Action to invoke upon graceful termination of the observable sequence.
|
||||
- returns: The source sequence with the side-effecting behavior applied.
|
||||
*/
|
||||
public func doOn(next next: (E throws -> Void)? = nil, error: (ErrorType throws -> Void)? = nil, completed: (() throws -> Void)? = nil)
|
||||
-> Observable<E> {
|
||||
return Do(source: self.asObservable()) { e in
|
||||
switch e {
|
||||
|
|
@ -50,10 +90,8 @@ extension ObservableType {
|
|||
try next?(element)
|
||||
case .Error(let e):
|
||||
try error?(e)
|
||||
try disposed?()
|
||||
case .Completed:
|
||||
try completed?()
|
||||
try disposed?()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -62,6 +100,13 @@ extension ObservableType {
|
|||
// startWith
|
||||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Prepends a sequence of values to an observable sequence.
|
||||
|
||||
- parameter elements: Elements to prepend to the specified sequence.
|
||||
- returns: The source sequence prepended with the specified values.
|
||||
*/
|
||||
public func startWith(elements: E ...)
|
||||
-> Observable<E> {
|
||||
return StartWith(source: self.asObservable(), elements: elements)
|
||||
|
|
@ -71,10 +116,24 @@ extension ObservableType {
|
|||
// retry
|
||||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Repeats the source observable sequence until it successfully terminates.
|
||||
|
||||
**This could potentially create an infinite sequence.**
|
||||
|
||||
- returns: Observable sequence to repeat until it successfully terminates.
|
||||
*/
|
||||
public func retry() -> Observable<E> {
|
||||
return CatchSequence(sources: InifiniteSequence(repeatedValue: self.asObservable()))
|
||||
return CatchSequence(sources: InfiniteSequence(repeatedValue: self.asObservable()))
|
||||
}
|
||||
|
||||
/**
|
||||
Repeats the source observable sequence the specified number of times in case of an error or until it successfully terminates.
|
||||
|
||||
- parameter retryCount: Number of times to repeat the sequence.
|
||||
- returns: An observable sequence producing the elements of the given sequence repeatedly until it terminates successfully.
|
||||
*/
|
||||
public func retry(retryCount: Int)
|
||||
-> Observable<E> {
|
||||
return CatchSequence(sources: Repeat(count: retryCount, repeatedValue: self.asObservable()))
|
||||
|
|
@ -85,9 +144,17 @@ extension ObservableType {
|
|||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Applies an accumulator function over an observable sequence and returns each intermediate result. The specified seed value is used as the initial accumulator value.
|
||||
|
||||
For aggregation behavior with no intermediate results, see `reduce`.
|
||||
|
||||
- parameter seed: The initial accumulator value.
|
||||
- parameter accumulator: An accumulator function to be invoked on each element.
|
||||
- returns: An observable sequence containing the accumulated values.
|
||||
*/
|
||||
public func scan<A>(seed: A, accumulator: (A, E) throws -> A)
|
||||
-> Observable<A> {
|
||||
return Scan(source: self.asObservable(), seed: seed, accumulator: accumulator)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -11,6 +11,13 @@ import Foundation
|
|||
// filter aka where
|
||||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Filters the elements of an observable sequence based on a predicate.
|
||||
|
||||
- parameter predicate: A function to test each source element for a condition.
|
||||
- returns: An observable sequence that contains elements from the input sequence that satisfy the condition.
|
||||
*/
|
||||
public func filter(predicate: (E) throws -> Bool)
|
||||
-> Observable<E> {
|
||||
return Filter(source: self.asObservable(), predicate: predicate)
|
||||
|
|
@ -20,11 +27,26 @@ extension ObservableType {
|
|||
// takeWhile
|
||||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Returns elements from an observable sequence as long as a specified condition is true.
|
||||
|
||||
- parameter predicate: A function to test each element for a condition.
|
||||
- returns: An observable sequence that contains the elements from the input sequence that occur before the element at which the test no longer passes.
|
||||
*/
|
||||
public func takeWhile(predicate: (E) -> Bool)
|
||||
-> Observable<E> {
|
||||
return TakeWhile(source: self.asObservable(), predicate: predicate)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns elements from an observable sequence as long as a specified condition is true.
|
||||
|
||||
The element's index is used in the logic of the predicate function.
|
||||
|
||||
- parameter predicate: A function to test each element for a condition; the second parameter of the function represents the index of the source element.
|
||||
- returns: An observable sequence that contains the elements from the input sequence that occur before the element at which the test no longer passes.
|
||||
*/
|
||||
public func takeWhile(predicate: (E, Int) -> Bool)
|
||||
-> Observable<E> {
|
||||
return TakeWhile(source: self.asObservable(), predicate: predicate)
|
||||
|
|
@ -34,6 +56,13 @@ extension ObservableType {
|
|||
// take
|
||||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Returns a specified number of contiguous elements from the start of an observable sequence.
|
||||
|
||||
- parameter count: The number of elements to return.
|
||||
- returns: An observable sequence that contains the specified number of elements from the start of the input sequence.
|
||||
*/
|
||||
public func take(count: Int)
|
||||
-> Observable<E> {
|
||||
if count == 0 {
|
||||
|
|
@ -48,6 +77,13 @@ extension ObservableType {
|
|||
// skip
|
||||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Bypasses a specified number of elements in an observable sequence and then returns the remaining elements.
|
||||
|
||||
- parameter count: The number of elements to skip before returning the remaining elements.
|
||||
- returns: An observable sequence that contains the elements that occur after the specified index in the input sequence.
|
||||
*/
|
||||
public func skip(count: Int)
|
||||
-> Observable<E> {
|
||||
return SkipCount(source: self.asObservable(), count: count)
|
||||
|
|
@ -57,11 +93,24 @@ extension ObservableType {
|
|||
// map aka select
|
||||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Projects each element of an observable sequence into a new form.
|
||||
|
||||
- parameter selector: A transform function to apply to each source element.
|
||||
- returns: An observable sequence whose elements are the result of invoking the transform function on each element of source.
|
||||
*/
|
||||
public func map<R>(selector: E throws -> R)
|
||||
-> Observable<R> {
|
||||
return Map(source: self.asObservable(), selector: selector)
|
||||
}
|
||||
|
||||
/**
|
||||
Projects each element of an observable sequence into a new form by incorporating the element's index.
|
||||
|
||||
- parameter selector: A transform function to apply to each source element; the second parameter of the function represents the index of the source element.
|
||||
- returns: An observable sequence whose elements are the result of invoking the transform function on each element of source.
|
||||
*/
|
||||
public func mapWithIndex<R>(selector: (E, Int) throws -> R)
|
||||
-> Observable<R> {
|
||||
return Map(source: self.asObservable(), selector: selector)
|
||||
|
|
@ -72,11 +121,23 @@ extension ObservableType {
|
|||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Projects each element of an observable sequence to an observable sequence and merges the resulting observable sequences into one observable sequence.
|
||||
|
||||
- parameter selector: A transform function to apply to each element.
|
||||
- returns: An observable sequence whose elements are the result of invoking the one-to-many transform function on each element of the input sequence.
|
||||
*/
|
||||
public func flatMap<O: ObservableType>(selector: (E) throws -> O)
|
||||
-> Observable<O.E> {
|
||||
return FlatMap(source: self.asObservable(), selector: selector)
|
||||
}
|
||||
|
||||
/**
|
||||
Projects each element of an observable sequence to an observable sequence by incorporating the element's index and merges the resulting observable sequences into one observable sequence.
|
||||
|
||||
- parameter selector: A transform function to apply to each element; the second parameter of the function represents the index of the source element.
|
||||
- returns: An observable sequence whose elements are the result of invoking the one-to-many transform function on each element of the input sequence.
|
||||
*/
|
||||
public func flatMapWithIndex<O: ObservableType>(selector: (E, Int) throws -> O)
|
||||
-> Observable<O.E> {
|
||||
return FlatMap(source: self.asObservable(), selector: selector)
|
||||
|
|
|
|||
|
|
@ -10,11 +10,30 @@ import Foundation
|
|||
|
||||
// throttle
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Ignores elements from an observable sequence which are followed by another element within a specified relative time duration, using the specified scheduler to run throttling timers.
|
||||
|
||||
`throttle` and `debounce` are synonyms.
|
||||
|
||||
- parameter dueTime: Throttling duration for each element.
|
||||
- parameter scheduler: Scheduler to run the throttle timers and send events on.
|
||||
- returns: The throttled sequence.
|
||||
*/
|
||||
public func throttle<S: Scheduler>(dueTime: S.TimeInterval, _ scheduler: S)
|
||||
-> Observable<E> {
|
||||
return Throttle(source: self.asObservable(), dueTime: dueTime, scheduler: scheduler)
|
||||
}
|
||||
|
||||
/**
|
||||
Ignores elements from an observable sequence which are followed by another element within a specified relative time duration, using the specified scheduler to run throttling timers.
|
||||
|
||||
`throttle` and `debounce` are synonyms.
|
||||
|
||||
- parameter dueTime: Throttling duration for each element.
|
||||
- parameter scheduler: Scheduler to run the throttle timers and send events on.
|
||||
- returns: The throttled sequence.
|
||||
*/
|
||||
public func debounce<S: Scheduler>(dueTime: S.TimeInterval, scheduler: S)
|
||||
-> Observable<E> {
|
||||
return Throttle(source: self.asObservable(), dueTime: dueTime, scheduler: scheduler)
|
||||
|
|
@ -24,14 +43,32 @@ extension ObservableType {
|
|||
// sample
|
||||
|
||||
extension ObservableType {
|
||||
// If there isn't a new value in `source` sequence from the last sample time
|
||||
// nothing will be forwarded.
|
||||
|
||||
/**
|
||||
Samples the source observable sequence using a samper observable sequence producing sampling ticks.
|
||||
|
||||
Upon each sampling tick, the latest element (if any) in the source sequence during the last sampling interval is sent to the resulting sequence.
|
||||
|
||||
**In case there were no new elements between sampler ticks, no element is sent to the resulting sequence.**
|
||||
|
||||
- parameter sampler: Sampling tick sequence.
|
||||
- returns: Sampled observable sequence.
|
||||
*/
|
||||
public func sample<O: ObservableType>(sampler: O)
|
||||
-> Observable<E> {
|
||||
return Sample(source: self.asObservable(), sampler: sampler.asObservable(), onlyNew: true)
|
||||
}
|
||||
|
||||
// On each sample latest element will always be forwarded.
|
||||
/**
|
||||
Samples the source observable sequence using a samper observable sequence producing sampling ticks.
|
||||
|
||||
Upon each sampling tick, the latest element (if any) in the source sequence during the last sampling interval is sent to the resulting sequence.
|
||||
|
||||
**In case there were no new elements between sampler ticks, last produced element is always sent to the resulting sequence.**
|
||||
|
||||
- parameter sampler: Sampling tick sequence.
|
||||
- returns: Sampled observable sequence.
|
||||
*/
|
||||
public func sampleLatest<O: ObservableType>(sampler: O)
|
||||
-> Observable<E> {
|
||||
return Sample(source: self.asObservable(), sampler: sampler.asObservable(), onlyNew: false)
|
||||
|
|
@ -40,6 +77,13 @@ extension ObservableType {
|
|||
|
||||
// interval
|
||||
|
||||
/**
|
||||
Returns an observable sequence that produces a value after each period, using the specified scheduler to run timers and to send out observer messages.
|
||||
|
||||
- parameter period: Period for producing the values in the resulting sequence.
|
||||
- parameter scheduler: Scheduler to run the timer on.
|
||||
- returns: An observable sequence that produces a value after each period.
|
||||
*/
|
||||
public func interval<S: Scheduler>(period: S.TimeInterval, _ scheduler: S)
|
||||
-> Observable<Int64> {
|
||||
return Timer(dueTime: period,
|
||||
|
|
@ -50,7 +94,15 @@ public func interval<S: Scheduler>(period: S.TimeInterval, _ scheduler: S)
|
|||
|
||||
// timer
|
||||
|
||||
public func timer<S: Scheduler>(dueTime: S.TimeInterval, _ period: S.TimeInterval, scheduler: S)
|
||||
/**
|
||||
Returns an observable sequence that periodically produces a value after the specified initial relative due time has elapsed, using the specified scheduler to run timers.
|
||||
|
||||
- parameter dueTime: Relative time at which to produce the first value.
|
||||
- parameter period: Period to produce subsequent values.
|
||||
- parameter scheduler: Scheduler to run timers on.
|
||||
- returns: An observable sequence that produces a value after due time has elapsed and then each period.
|
||||
*/
|
||||
public func timer<S: Scheduler>(dueTime: S.TimeInterval, _ period: S.TimeInterval, _ scheduler: S)
|
||||
-> Observable<Int64> {
|
||||
return Timer(
|
||||
dueTime: dueTime,
|
||||
|
|
@ -59,7 +111,14 @@ public func timer<S: Scheduler>(dueTime: S.TimeInterval, _ period: S.TimeInterva
|
|||
)
|
||||
}
|
||||
|
||||
public func timer<S: Scheduler>(dueTime: S.TimeInterval, scheduler: S)
|
||||
/**
|
||||
Returns an observable sequence that produces a single value at the specified absolute due time, using the specified scheduler to run the timer.
|
||||
|
||||
- parameter dueTime: Time interval after which to produce the value.
|
||||
- parameter scheduler: Scheduler to run the timer on.
|
||||
- returns: An observable sequence that produces a value at due time.
|
||||
*/
|
||||
public func timer<S: Scheduler>(dueTime: S.TimeInterval, _ scheduler: S)
|
||||
-> Observable<Int64> {
|
||||
return Timer(
|
||||
dueTime: dueTime,
|
||||
|
|
@ -71,6 +130,14 @@ public func timer<S: Scheduler>(dueTime: S.TimeInterval, scheduler: S)
|
|||
// take
|
||||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Takes elements for the specified duration from the start of the observable source sequence, using the specified scheduler to run timers.
|
||||
|
||||
- parameter duration: Duration for taking elements from the start of the sequence.
|
||||
- parameter scheduler: Scheduler to run the timer on.
|
||||
- returns: An observable sequence with the elements taken during the specified duration from the start of the source sequence.
|
||||
*/
|
||||
public func take<S: Scheduler>(duration: S.TimeInterval, _ scheduler: S)
|
||||
-> Observable<E> {
|
||||
return TakeTime(source: self.asObservable(), duration: duration, scheduler: scheduler)
|
||||
|
|
@ -80,6 +147,14 @@ extension ObservableType {
|
|||
// skip
|
||||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Skips elements for the specified duration from the start of the observable source sequence, using the specified scheduler to run timers.
|
||||
|
||||
- parameter duration: Duration for skipping elements from the start of the sequence.
|
||||
- parameter scheduler: Scheduler to run the timer on.
|
||||
- returns: An observable sequence with the elements skipped during the specified duration from the start of the source sequence.
|
||||
*/
|
||||
public func skip<S: Scheduler>(duration: S.TimeInterval, _ scheduler: S)
|
||||
-> Observable<E> {
|
||||
return SkipTime(source: self.asObservable(), duration: duration, scheduler: scheduler)
|
||||
|
|
@ -90,6 +165,14 @@ extension ObservableType {
|
|||
// delaySubscription
|
||||
|
||||
extension ObservableType {
|
||||
|
||||
/**
|
||||
Time shifts the observable sequence by delaying the subscription with the specified relative time duration, using the specified scheduler to run timers.
|
||||
|
||||
- parameter dueTime: Relative time shift of the subscription.
|
||||
- parameter scheduler: Scheduler to run the subscription delay timer on.
|
||||
- returns: Time-shifted sequence.
|
||||
*/
|
||||
public func delaySubscription<S: Scheduler>(dueTime: S.TimeInterval, _ scheduler: S)
|
||||
-> Observable<E> {
|
||||
return DelaySubscription(source: self.asObservable(), dueTime: dueTime, scheduler: scheduler)
|
||||
|
|
|
|||
|
|
@ -8,9 +8,11 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
// This is a base class for all of the internal observers/sinks
|
||||
public class Observer<ElementType> : ObserverType {
|
||||
public typealias E = ElementType
|
||||
/**
|
||||
This is a base class for all of the internal observers/sinks
|
||||
*/
|
||||
class Observer<ElementType> : ObserverType {
|
||||
typealias E = ElementType
|
||||
|
||||
init() {
|
||||
#if TRACE_RESOURCES
|
||||
|
|
@ -18,7 +20,7 @@ public class Observer<ElementType> : ObserverType {
|
|||
#endif
|
||||
}
|
||||
|
||||
public func on(event: Event<E>) {
|
||||
func on(event: Event<E>) {
|
||||
return abstractMethod()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,32 +8,60 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
A type-erased `ObserverType`.
|
||||
|
||||
Forwards operations to an arbitrary underlying observer with the same `Element` type, hiding the specifics of the underlying observer type.
|
||||
*/
|
||||
public struct ObserverOf<Element> : ObserverType {
|
||||
/**
|
||||
The type of elements in sequence that observer can observe.
|
||||
*/
|
||||
public typealias E = Element
|
||||
|
||||
public typealias SinkType = (Event<Element>) -> Void
|
||||
/**
|
||||
Anonymous event handler type.
|
||||
*/
|
||||
public typealias EventHandler = (Event<Element>) -> Void
|
||||
|
||||
public let sink: SinkType
|
||||
public let observer: EventHandler
|
||||
|
||||
/// Construct an instance whose `on(event)` calls `sink(event)`
|
||||
public init(sink: SinkType) {
|
||||
self.sink = sink
|
||||
/**
|
||||
Construct an instance whose `on(event)` calls `eventHandler(event)`
|
||||
|
||||
- parameter eventHandler: Event handler that observes sequences events.
|
||||
*/
|
||||
public init(eventHandler: EventHandler) {
|
||||
self.observer = eventHandler
|
||||
}
|
||||
|
||||
/// Construct an instance whose `on(event)` calls `observer.on(event)`
|
||||
/**
|
||||
Construct an instance whose `on(event)` calls `observer.on(event)`
|
||||
|
||||
- parameter observer: Observer that receives sequence events.
|
||||
*/
|
||||
public init<O : ObserverType where O.E == Element>(_ observer: O) {
|
||||
self.sink = { e in
|
||||
self.observer = { e in
|
||||
return observer.on(e)
|
||||
}
|
||||
}
|
||||
|
||||
/// Send `event` to this observer.
|
||||
/**
|
||||
Send `event` to this observer.
|
||||
|
||||
- parameter event: Event instance.
|
||||
*/
|
||||
public func on(event: Event<Element>) {
|
||||
return self.sink(event)
|
||||
return self.observer(event)
|
||||
}
|
||||
}
|
||||
|
||||
extension ObserverType {
|
||||
/**
|
||||
Erases type of observer and returns canonical observer.
|
||||
|
||||
- returns: type erased observer.
|
||||
*/
|
||||
func asObserver() -> ObserverOf<E> {
|
||||
return ObserverOf(self)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,19 +8,22 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
|
||||
@available(*, deprecated=2.0.0, message="Please use observer.on(event)")
|
||||
public func send<O: ObserverType>(observer: O, _ event: Event<O.E>) {
|
||||
observer.on(event)
|
||||
}
|
||||
|
||||
@available(*, deprecated=2.0.0, message="Please use observer.on(.Next(element))")
|
||||
public func sendNext<O: ObserverType>(observer: O, _ element: O.E) {
|
||||
observer.on(.Next(element))
|
||||
}
|
||||
|
||||
@available(*, deprecated=2.0.0, message="Please use observer.on(.Error(error))")
|
||||
public func sendError<O: ObserverType>(observer: O, _ error: ErrorType) {
|
||||
observer.on(.Error(error))
|
||||
}
|
||||
|
||||
@available(*, deprecated=2.0.0, message="Please use observer.on(.Completed)")
|
||||
public func sendCompleted<O: ObserverType>(observer: O) {
|
||||
observer.on(.Completed)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,11 +8,20 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Supports push-style iteration over an observable sequence.
|
||||
*/
|
||||
public protocol ObserverType {
|
||||
/// The type of event to be written to this observer.
|
||||
/**
|
||||
The type of elements in sequence that observer can observe.
|
||||
*/
|
||||
typealias E
|
||||
|
||||
/// Send `event` to this observer.
|
||||
/**
|
||||
Notify observer about sequence event.
|
||||
|
||||
- parameter event: Event that occured.
|
||||
*/
|
||||
func on(event: Event<E>)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,14 +8,14 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
public class AnonymousObserver<ElementType> : ObserverBase<ElementType> {
|
||||
public typealias Element = ElementType
|
||||
class AnonymousObserver<ElementType> : ObserverBase<ElementType> {
|
||||
typealias Element = ElementType
|
||||
|
||||
public typealias EventHandler = Event<Element> -> Void
|
||||
typealias EventHandler = Event<Element> -> Void
|
||||
|
||||
private let eventHandler : EventHandler
|
||||
|
||||
public init(_ eventHandler: EventHandler) {
|
||||
init(_ eventHandler: EventHandler) {
|
||||
#if TRACE_RESOURCES
|
||||
OSAtomicIncrement32(&resourceCount)
|
||||
#endif
|
||||
|
|
@ -26,7 +26,7 @@ public class AnonymousObserver<ElementType> : ObserverBase<ElementType> {
|
|||
return AnonymousSafeObserver(self.eventHandler, disposable: disposable)
|
||||
}
|
||||
|
||||
public override func onCore(event: Event<Element>) {
|
||||
override func onCore(event: Event<Element>) {
|
||||
return self.eventHandler(event)
|
||||
}
|
||||
|
||||
|
|
@ -37,17 +37,17 @@ public class AnonymousObserver<ElementType> : ObserverBase<ElementType> {
|
|||
#endif
|
||||
}
|
||||
|
||||
public class AnonymousSafeObserver<ElementType> : Observer<ElementType> {
|
||||
public typealias Element = ElementType
|
||||
class AnonymousSafeObserver<ElementType> : Observer<ElementType> {
|
||||
typealias Element = ElementType
|
||||
|
||||
public typealias EventHandler = Event<Element> -> Void
|
||||
typealias EventHandler = Event<Element> -> Void
|
||||
|
||||
private let eventHandler : EventHandler
|
||||
private let disposable: Disposable
|
||||
|
||||
var stopped: Int32 = 0
|
||||
|
||||
public init(_ eventHandler: EventHandler, disposable: Disposable) {
|
||||
init(_ eventHandler: EventHandler, disposable: Disposable) {
|
||||
#if TRACE_RESOURCES
|
||||
OSAtomicIncrement32(&resourceCount)
|
||||
#endif
|
||||
|
|
@ -55,7 +55,7 @@ public class AnonymousSafeObserver<ElementType> : Observer<ElementType> {
|
|||
self.disposable = disposable
|
||||
}
|
||||
|
||||
public override func on(event: Event<Element>) {
|
||||
override func on(event: Event<Element>) {
|
||||
switch event {
|
||||
case .Next:
|
||||
if stopped == 0 {
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
public class NopObserver<ElementType> : ObserverType {
|
||||
public typealias Element = ElementType
|
||||
class NopObserver<ElementType> : ObserverType {
|
||||
typealias Element = ElementType
|
||||
|
||||
public init() {
|
||||
init() {
|
||||
|
||||
}
|
||||
|
||||
public func on(event: Event<Element>) {
|
||||
func on(event: Event<Element>) {
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
//
|
||||
// ScheduledObserver.swift
|
||||
// RxSwift
|
||||
//
|
||||
// Created by Krunoslav Zaher on 7/25/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
// This class is usually used with `GeneratorOf` version of the operators.
|
||||
/// This class is usually used with `Generator` version of the operators.
|
||||
class TailRecursiveSink<S: SequenceType, O: ObserverType where S.Generator.Element: ObservableType, S.Generator.Element.E == O.E> : Sink<O>, ObserverType {
|
||||
typealias E = O.E
|
||||
|
||||
|
|
|
|||
|
|
@ -8,24 +8,14 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
public func justUseIt<T>(_: T) {
|
||||
|
||||
}
|
||||
|
||||
#if TRACE_RESOURCES
|
||||
// counts resources
|
||||
// used to detect resource leaks during unit tests
|
||||
// it's not perfect, but works well
|
||||
public var resourceCount: Int32 = 0
|
||||
public var numberOfSerialDispatchQueueObservables: Int32 = 0
|
||||
#endif
|
||||
/**
|
||||
Counts internal Rx resources (Observables, Observers, Disposables ...).
|
||||
|
||||
func contract(@autoclosure condition: () -> Bool) {
|
||||
if !condition() {
|
||||
let exception = NSException(name: "ContractError", reason: "Contract failed", userInfo: nil)
|
||||
exception.raise()
|
||||
}
|
||||
}
|
||||
It provides a really simple way to detect leaks early during development.
|
||||
*/
|
||||
public var resourceCount: Int32 = 0
|
||||
#endif
|
||||
|
||||
// Swift doesn't have a concept of abstract metods.
|
||||
// This function is being used as a runtime check that abstract methods aren't being called.
|
||||
|
|
|
|||
|
|
@ -8,13 +8,27 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
// Wrapper for any value type
|
||||
/**
|
||||
Creates immutable reference wrapper for any type.
|
||||
*/
|
||||
public class RxBox<T> : CustomStringConvertible {
|
||||
/**
|
||||
Wrapped value
|
||||
*/
|
||||
public let value : T
|
||||
|
||||
/**
|
||||
Creates reference wrapper for `value`.
|
||||
|
||||
- parameter value: Value to wrap.
|
||||
*/
|
||||
public init (_ value: T) {
|
||||
self.value = value
|
||||
}
|
||||
|
||||
/**
|
||||
- returns: Box description.
|
||||
*/
|
||||
public var description: String {
|
||||
get {
|
||||
return "Box(\(self.value))"
|
||||
|
|
@ -22,13 +36,27 @@ public class RxBox<T> : CustomStringConvertible {
|
|||
}
|
||||
}
|
||||
|
||||
// Wrapper for any value type that can be mutated
|
||||
/**
|
||||
Creates mutable reference wrapper for any type.
|
||||
*/
|
||||
public class RxMutableBox<T> : CustomStringConvertible {
|
||||
/**
|
||||
Wrapped value
|
||||
*/
|
||||
public var value : T
|
||||
|
||||
/**
|
||||
Creates reference wrapper for `value`.
|
||||
|
||||
- parameter value: Value to wrap.
|
||||
*/
|
||||
public init (_ value: T) {
|
||||
self.value = value
|
||||
}
|
||||
|
||||
/**
|
||||
- returns: Box description.
|
||||
*/
|
||||
public var description: String {
|
||||
get {
|
||||
return "MutatingBox(\(self.value))"
|
||||
|
|
|
|||
|
|
@ -1,187 +0,0 @@
|
|||
//
|
||||
// RxResult.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/12/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
// Represents computation result.
|
||||
//
|
||||
// The result can be either successful or failure.
|
||||
//
|
||||
// It's a port of Scala (originally Twitter) `Try` type
|
||||
// http://www.scala-lang.org/api/2.10.2/index.html#scala.util.Try
|
||||
// The name `Result` was chosen because it better describes it's common usage.
|
||||
//
|
||||
// The reason why it's named differently is because `Try` doesn't make sense in the context
|
||||
// of swift.
|
||||
//
|
||||
// In scala it would be used like `Try { throw new Exception("oh dear") }`
|
||||
//
|
||||
// The reason why `Result` has `Rx` prefix is because there could be name collisions with other
|
||||
// result types.
|
||||
//
|
||||
public enum RxResult<T> {
|
||||
case Success(T)
|
||||
case Failure(ErrorType)
|
||||
}
|
||||
|
||||
extension RxResult {
|
||||
|
||||
// Returns true if `self` is a `Success`, false otherwise.
|
||||
public var isSuccess: Bool {
|
||||
get {
|
||||
switch self {
|
||||
case .Success:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if `self` is a `Failure`, false otherwise.
|
||||
public var isFailure: Bool {
|
||||
get {
|
||||
switch self {
|
||||
case .Failure:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the given function applied to the value from `Success` or returns `self` if this is a `Failure`.
|
||||
public func flatMap<U>(@noescape f: T -> RxResult<U>) -> RxResult<U> {
|
||||
switch self {
|
||||
case .Success(let value):
|
||||
return f(value)
|
||||
case .Failure(let error):
|
||||
return failure(error)
|
||||
}
|
||||
}
|
||||
|
||||
// Maps the given function to the value from `Success` or returns `self` if this is a `Failure`.
|
||||
public func map<U>(@noescape f: T -> U) -> RxResult<U> {
|
||||
switch self {
|
||||
case .Success(let value):
|
||||
return success(f(value))
|
||||
case .Failure(let error):
|
||||
return failure(error)
|
||||
}
|
||||
}
|
||||
|
||||
// Applies the given function `f` if this is a `Failure`, otherwise returns `self` if this is a `Success`.
|
||||
public func recover(@noescape f: (ErrorType) -> T) -> RxResult<T> {
|
||||
switch self {
|
||||
case .Success(_):
|
||||
return self
|
||||
case .Failure(let error):
|
||||
return success(f(error))
|
||||
}
|
||||
}
|
||||
|
||||
// Applies the given function `f` if this is a `Failure`, otherwise returns `self` if this is a `Success`.
|
||||
public func recoverWith(@noescape f: (ErrorType) -> RxResult<T>) -> RxResult<T> {
|
||||
switch self {
|
||||
case .Success(_):
|
||||
return self
|
||||
case .Failure(let error):
|
||||
return f(error)
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the value if `Success` or throws the exception if this is a Failure.
|
||||
public func get() -> T {
|
||||
switch self {
|
||||
case .Success(let value):
|
||||
return value
|
||||
case .Failure(let error):
|
||||
rxFatalError("Result represents failure: \(error)")
|
||||
return (nil as T?)!
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the value if `Success` or the given `defaultValue` if this is a `Failure`.
|
||||
public func getOrElse(defaultValue: T) -> T {
|
||||
switch self {
|
||||
case .Success(let value):
|
||||
return value
|
||||
case .Failure(_):
|
||||
return defaultValue
|
||||
}
|
||||
}
|
||||
|
||||
// Returns `self` if `Success` or the given `defaultValue` if this is a `Failure`.
|
||||
public func getOrElse(defaultValue: RxResult<T>) -> RxResult<T> {
|
||||
switch self {
|
||||
case .Success(_):
|
||||
return self
|
||||
case .Failure(_):
|
||||
return defaultValue
|
||||
}
|
||||
}
|
||||
|
||||
// Returns `nil` if this is a `Failure` or a `T` containing the value if this is a `Success`
|
||||
public func toOptional() -> T? {
|
||||
switch self {
|
||||
case .Success(let value):
|
||||
return value
|
||||
case .Failure(_):
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// convenience constructor
|
||||
|
||||
public func success<T>(value: T) -> RxResult<T> {
|
||||
return .Success(value)
|
||||
}
|
||||
|
||||
public func failure<T>(error: ErrorType) -> RxResult<T> {
|
||||
return .Failure(error)
|
||||
}
|
||||
|
||||
public let SuccessResult = success(())
|
||||
|
||||
// lift functions
|
||||
|
||||
// "Lifts" functions that take normal arguments to functions that take `Result` monad arguments.
|
||||
// Unfortunately these are not generic `Monad` lift functions because
|
||||
// Creating generic lift functions that work for arbitrary monads is a lot more tricky.
|
||||
|
||||
func lift<T1, TRet>(function: (T1) -> TRet) -> (RxResult<T1>) -> RxResult<TRet> {
|
||||
return { arg1 in
|
||||
return arg1.map { value1 in
|
||||
return function(value1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func lift<T1, T2, TRet>(function: (T1, T2) -> TRet) -> (RxResult<T1>, RxResult<T2>) -> RxResult<TRet> {
|
||||
return { arg1, arg2 in
|
||||
return arg1.flatMap { value1 in
|
||||
return arg2.map { value2 in
|
||||
return function(value1, value2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func lift<T1, T2, T3, TRet>(function: (T1, T2, T3) -> TRet) -> (RxResult<T1>, RxResult<T2>, RxResult<T3>) -> RxResult<TRet> {
|
||||
return { arg1, arg2, arg3 in
|
||||
return arg1.flatMap { value1 in
|
||||
return arg2.flatMap { value2 in
|
||||
return arg3.map { value3 in
|
||||
return function(value1, value2, value3)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8,16 +8,63 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Represents an object that schedules units of work.
|
||||
*/
|
||||
public protocol Scheduler: ImmediateScheduler {
|
||||
/**
|
||||
Type that represents time interval in the context of this scheduler.
|
||||
*/
|
||||
typealias TimeInterval
|
||||
|
||||
/**
|
||||
Type that represents absolute time in the context of this scheduler.
|
||||
*/
|
||||
typealias Time
|
||||
|
||||
/**
|
||||
- returns: Current time.
|
||||
*/
|
||||
var now : Time {
|
||||
get
|
||||
}
|
||||
|
||||
/**
|
||||
Schedules an action to be executed.
|
||||
|
||||
- parameter state: State passed to the action to be executed.
|
||||
- parameter dueTime: Relative time after which to execute the action.
|
||||
- parameter action: Action to be executed.
|
||||
- returns: The disposable object used to cancel the scheduled action (best effort).
|
||||
*/
|
||||
func scheduleRelative<StateType>(state: StateType, dueTime: TimeInterval, action: (StateType) -> Disposable) -> Disposable
|
||||
|
||||
/**
|
||||
Schedules a periodic piece of work.
|
||||
|
||||
- parameter state: State passed to the action to be executed.
|
||||
- parameter startAfter: Period after which initial work should be run.
|
||||
- parameter period: Period for running the work periodically.
|
||||
- parameter action: Action to be executed.
|
||||
- returns: The disposable object used to cancel the scheduled action (best effort).
|
||||
*/
|
||||
func schedulePeriodic<StateType>(state: StateType, startAfter: TimeInterval, period: TimeInterval, action: (StateType) -> StateType) -> Disposable
|
||||
}
|
||||
|
||||
extension Scheduler {
|
||||
public func schedulePeriodic<StateType>(state: StateType, startAfter: TimeInterval, period: TimeInterval, action: (StateType) -> StateType) -> Disposable {
|
||||
let schedule = SchedulePeriodicRecursive(scheduler: self, startAfter: startAfter, period: period, action: action, state: state)
|
||||
|
||||
return schedule.start()
|
||||
}
|
||||
|
||||
func scheduleRecursive<State>(state: State, dueTime: TimeInterval, action: (state: State, scheduler: RecursiveSchedulerOf<State, TimeInterval>) -> Void) -> Disposable {
|
||||
let scheduler = RecursiveScheduler(scheduler: self, action: action)
|
||||
|
||||
scheduler.schedule(state, dueTime: dueTime)
|
||||
|
||||
return AnonymousDisposable {
|
||||
scheduler.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,11 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Abstracts the work that needs to be peformed on a specific `dispatch_queue_t`. You can also pass a serial dispatch queue, it shouldn't cause any problems.
|
||||
|
||||
This scheduler is suitable when some work needs to be performed in background.
|
||||
*/
|
||||
public class ConcurrentDispatchQueueScheduler: Scheduler {
|
||||
public typealias TimeInterval = NSTimeInterval
|
||||
public typealias Time = NSDate
|
||||
|
|
@ -23,15 +28,20 @@ public class ConcurrentDispatchQueueScheduler: Scheduler {
|
|||
// leeway for scheduling timers
|
||||
var leeway: Int64 = 0
|
||||
|
||||
/**
|
||||
Constructs new `ConcurrentDispatchQueueScheduler` that wraps `queue`.
|
||||
|
||||
- parameter queue: Target dispatch queue.
|
||||
*/
|
||||
public init(queue: dispatch_queue_t) {
|
||||
self.queue = queue
|
||||
}
|
||||
|
||||
// Convenience init for scheduler that wraps one of the global concurrent dispatch queues.
|
||||
//
|
||||
// DISPATCH_QUEUE_PRIORITY_DEFAULT
|
||||
// DISPATCH_QUEUE_PRIORITY_HIGH
|
||||
// DISPATCH_QUEUE_PRIORITY_LOW
|
||||
/**
|
||||
Convenience init for scheduler that wraps one of the global concurrent dispatch queues.
|
||||
|
||||
- parameter globalConcurrentQueuePriority: Target global dispatch queue.
|
||||
*/
|
||||
public convenience init(globalConcurrentQueuePriority: DispatchQueueSchedulerPriority) {
|
||||
var priority: Int = 0
|
||||
switch globalConcurrentQueuePriority {
|
||||
|
|
@ -53,6 +63,13 @@ public class ConcurrentDispatchQueueScheduler: Scheduler {
|
|||
return dispatch_time(DISPATCH_TIME_NOW, convertTimeIntervalToDispatchInterval(timeInterval))
|
||||
}
|
||||
|
||||
/**
|
||||
Schedules an action to be executed immediatelly.
|
||||
|
||||
- parameter state: State passed to the action to be executed.
|
||||
- parameter action: Action to be executed.
|
||||
- returns: The disposable object used to cancel the scheduled action (best effort).
|
||||
*/
|
||||
public final func schedule<StateType>(state: StateType, action: StateType -> Disposable) -> Disposable {
|
||||
return self.scheduleInternal(state, action: action)
|
||||
}
|
||||
|
|
@ -71,6 +88,14 @@ public class ConcurrentDispatchQueueScheduler: Scheduler {
|
|||
return cancel
|
||||
}
|
||||
|
||||
/**
|
||||
Schedules an action to be executed.
|
||||
|
||||
- parameter state: State passed to the action to be executed.
|
||||
- parameter dueTime: Relative time after which to execute the action.
|
||||
- parameter action: Action to be executed.
|
||||
- returns: The disposable object used to cancel the scheduled action (best effort).
|
||||
*/
|
||||
public final func scheduleRelative<StateType>(state: StateType, dueTime: NSTimeInterval, action: (StateType) -> Disposable) -> Disposable {
|
||||
let timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.queue)
|
||||
|
||||
|
|
@ -94,7 +119,16 @@ public class ConcurrentDispatchQueueScheduler: Scheduler {
|
|||
return compositeDisposable
|
||||
}
|
||||
|
||||
public func schedulePeriodic<StateType>(state: StateType, startAfter: TimeInterval, period: TimeInterval, action: (StateType) -> StateType) -> RxResult<Disposable> {
|
||||
/**
|
||||
Schedules a periodic piece of work.
|
||||
|
||||
- parameter state: State passed to the action to be executed.
|
||||
- parameter startAfter: Period after which initial work should be run.
|
||||
- parameter period: Period for running the work periodically.
|
||||
- parameter action: Action to be executed.
|
||||
- returns: The disposable object used to cancel the scheduled action (best effort).
|
||||
*/
|
||||
public func schedulePeriodic<StateType>(state: StateType, startAfter: TimeInterval, period: TimeInterval, action: (StateType) -> StateType) -> Disposable {
|
||||
let timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.queue)
|
||||
|
||||
let initial = MainScheduler.convertTimeIntervalToDispatchTime(startAfter)
|
||||
|
|
@ -116,6 +150,6 @@ public class ConcurrentDispatchQueueScheduler: Scheduler {
|
|||
})
|
||||
dispatch_resume(timer)
|
||||
|
||||
return success(cancel)
|
||||
return cancel
|
||||
}
|
||||
}
|
||||
|
|
@ -8,8 +8,23 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Identifies one of the global concurrent dispatch queues with specified priority.
|
||||
*/
|
||||
public enum DispatchQueueSchedulerPriority {
|
||||
|
||||
/**
|
||||
Identifies global dispatch queue with `DISPATCH_QUEUE_PRIORITY_HIGH`
|
||||
*/
|
||||
case High
|
||||
|
||||
/**
|
||||
Identifies global dispatch queue with `DISPATCH_QUEUE_PRIORITY_DEFAULT`
|
||||
*/
|
||||
case Default
|
||||
|
||||
/**
|
||||
Identifies global dispatch queue with `DISPATCH_QUEUE_PRIORITY_LOW`
|
||||
*/
|
||||
case Low
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,17 +8,30 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Abstracts work that needs to be performed on `MainThread`. In case `schedule` methods are called from main thread, it will perform action immediately without scheduling.
|
||||
|
||||
This scheduler is usually used to perform UI work.
|
||||
|
||||
Main scheduler is a specialization of `SerialDispatchQueueScheduler`.
|
||||
*/
|
||||
public final class MainScheduler : SerialDispatchQueueScheduler {
|
||||
|
||||
private init() {
|
||||
super.init(serialQueue: dispatch_get_main_queue())
|
||||
}
|
||||
|
||||
/**
|
||||
Singleton instance of `MainScheduler`
|
||||
*/
|
||||
public static let sharedInstance: MainScheduler = MainScheduler()
|
||||
|
||||
/**
|
||||
In case this method is called on a background thread it will throw an exception.
|
||||
*/
|
||||
public class func ensureExecutingOnScheduler() {
|
||||
if !NSThread.currentThread().isMainThread {
|
||||
rxFatalError("Executing on scheduler that is not main. Please use `MainScheduler.sharedInstance`.")
|
||||
rxFatalError("Executing on backgound thread. Please use `MainScheduler.sharedInstance.schedule` to schedule work on main thread.")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue