Skip to content

Commit

Permalink
Performance improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
srdanrasic committed Nov 23, 2015
1 parent be9d892 commit 924d114
Show file tree
Hide file tree
Showing 19 changed files with 279 additions and 305 deletions.
4 changes: 2 additions & 2 deletions ReactiveKit.podspec
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
Pod::Spec.new do |s|
s.name = "ReactiveKit"
s.version = "1.0.5"
s.version = "1.0.6"
s.summary = "A Swift Reactive Programming Framework"
s.description = "ReactiveKit is a collection of Swift frameworks for reactive and functional reactive programming."
s.homepage = "https://github.com/ReactiveKit/ReactiveKit"
s.license = 'MIT'
s.author = { "Srdan Rasic" => "[email protected]" }
s.source = { :git => "https://github.com/ReactiveKit/ReactiveKit.git", :tag => "v1.0.5" }
s.source = { :git => "https://github.com/ReactiveKit/ReactiveKit.git", :tag => "v1.0.6" }

s.ios.deployment_target = '8.0'
s.osx.deployment_target = '10.9'
Expand Down
55 changes: 29 additions & 26 deletions ReactiveKit.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion ReactiveKit/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0.5</string>
<string>1.0.6</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
Expand Down
2 changes: 1 addition & 1 deletion ReactiveKit/Observable/MutableObservable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public struct MutableObservable<Value>: ObservableType {
observable = Observable(value)
}

public func observe(on context: ExecutionContext, observer: Value -> ()) -> DisposableType {
public func observe(on context: ExecutionContext? = ImmediateOnMainExecutionContext, observer: Value -> ()) -> DisposableType {
return observable.observe(on: context, observer: observer)
}
}
37 changes: 11 additions & 26 deletions ReactiveKit/Observable/Observable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,37 +27,22 @@ public protocol ObservableType: StreamType {
var value: Value { get set }
}

public class Observable<Value>: ActiveStream<Value>, ObservableType {
public final class Observable<Value>: ActiveStream<Value>, ObservableType {

public var value: Value {
get {
return try! lastEvent()
}
set {
capturedObserver?(newValue)
didSet {
next(value)
}
}

private var capturedObserver: (Value -> ())? = nil


public init(_ value: Value) {
var capturedObserver: (Value -> ())!
super.init(limit: 1, producer: { observer in
capturedObserver = observer
observer(value)
return nil
})
self.capturedObserver = capturedObserver
self.value = value
super.init()
}

public init(@noescape producer: (Value -> ()) -> DisposableType?) {
super.init(limit: 1, producer: { observer in
return producer(observer)
})
}
}

@warn_unused_result
public func create<Value>(producer: (Value -> ()) -> DisposableType?) -> Observable<Value> {
return Observable(producer: producer)
public override func observe(on context: ExecutionContext? = ImmediateOnMainExecutionContext, observer: Observer) -> DisposableType {
let disposable = super.observe(on: context, observer: observer)
observer(value)
return disposable
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,37 +22,34 @@
// THE SOFTWARE.
//

public class StreamBuffer<Event> {
public var array: [Event] = []
public final class ObservableBuffer<Event>: ActiveStream<Event> {

public var buffer: [Event] = []
public let limit: Int

public init(limit: Int = Int.max) {
self.limit = limit
super.init()
}

public func next(event: Event) {
array.append(event)
if array.count > limit {
array = Array(array.suffixFrom(1))
}

public init(limit: Int = Int.max, @noescape producer: Observer -> DisposableType?) {
self.limit = limit
super.init(producer: producer)
}

public func replay(observer: Event -> ()) {
for value in array {
observer(value)

public override func next(event: Event) {
buffer.append(event)
if buffer.count > limit {
buffer = Array(buffer.suffixFrom(1))
}
super.next(event)
}

public func last() throws -> Event {
if array.count > 0 {
return array.last!
} else {
throw StreamBufferError.NoEvent

public override func observe(on context: ExecutionContext? = ImmediateOnMainExecutionContext, observer: Observer) -> DisposableType {
let disposable = super.observe(on: context, observer: observer)
for event in buffer {
observer(event)
}
return disposable
}
}

public enum StreamBufferError: ErrorType {
case NoEvent
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ public struct MutableObservableCollection<Collection: CollectionType>: Observabl
observableCollection = ObservableCollection(collection)
}

public mutating func dispatch(event: ObservableCollectionEvent<Collection>) {
observableCollection.dispatch(event)
public mutating func next(event: ObservableCollectionEvent<Collection>) {
observableCollection.next(event)
}

public func observe(on context: ExecutionContext, observer: ObservableCollectionEvent<Collection> -> ()) -> DisposableType {
public func observe(on context: ExecutionContext? = ImmediateOnMainExecutionContext, observer: ObservableCollectionEvent<Collection> -> ()) -> DisposableType {
return observableCollection.observe(on: context, observer: observer)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,38 +27,38 @@ extension ObservableCollectionType where Collection == Array<Element> {
public mutating func append(x: Collection.Generator.Element) {
var new = collection
new.append(x)
dispatch(ObservableCollectionEvent(collection: new, inserts: [collection.count], deletes: [], updates: []))
next(ObservableCollectionEvent(collection: new, inserts: [collection.count], deletes: [], updates: []))
}

public mutating func insert(newElement: Collection.Generator.Element, atIndex: Int) {
var new = collection
new.insert(newElement, atIndex: atIndex)
dispatch(ObservableCollectionEvent(collection: new, inserts: [atIndex], deletes: [], updates: []))
next(ObservableCollectionEvent(collection: new, inserts: [atIndex], deletes: [], updates: []))
}

public mutating func insertContentsOf(newElements: [Collection.Generator.Element], at index: Collection.Index) {
var new = collection
new.insertContentsOf(newElements, at: index)
dispatch(ObservableCollectionEvent(collection: new, inserts: Array(index..<index+newElements.count), deletes: [], updates: []))
next(ObservableCollectionEvent(collection: new, inserts: Array(index..<index+newElements.count), deletes: [], updates: []))
}

public mutating func removeAtIndex(index: Int) -> Collection.Generator.Element {
var new = collection
let element = new.removeAtIndex(index)
dispatch(ObservableCollectionEvent(collection: new, inserts: [], deletes: [index], updates: []))
next(ObservableCollectionEvent(collection: new, inserts: [], deletes: [index], updates: []))
return element
}

public mutating func removeLast() -> Collection.Generator.Element {
var new = collection
let element = new.removeLast()
dispatch(ObservableCollectionEvent(collection: new, inserts: [], deletes: [new.count], updates: []))
next(ObservableCollectionEvent(collection: new, inserts: [], deletes: [new.count], updates: []))
return element
}

public mutating func removeAll() {
let deletes = Array(0..<collection.count)
dispatch(ObservableCollectionEvent(collection: [], inserts: [], deletes: deletes, updates: []))
next(ObservableCollectionEvent(collection: [], inserts: [], deletes: deletes, updates: []))
}

public subscript(index: Collection.Index) -> Collection.Generator.Element {
Expand All @@ -68,7 +68,7 @@ extension ObservableCollectionType where Collection == Array<Element> {
set {
var new = collection
new[index] = newValue
dispatch(ObservableCollectionEvent(collection: new, inserts: [], deletes: [], updates: [index]))
next(ObservableCollectionEvent(collection: new, inserts: [], deletes: [], updates: [index]))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@ extension ObservableCollectionType where Index: DictionaryIndexType, Collection
var new = collection
if let index = new.indexForKey(key) {
let oldValue = new.updateValue(value, forKey: key)
dispatch(ObservableCollectionEvent(collection: new, inserts: [], deletes: [], updates: [index]))
next(ObservableCollectionEvent(collection: new, inserts: [], deletes: [], updates: [index]))
return oldValue
} else {
new.updateValue(value, forKey: key)
let index = new.indexForKey(key)!
dispatch(ObservableCollectionEvent(collection: new, inserts: [index], deletes: [], updates: []))
next(ObservableCollectionEvent(collection: new, inserts: [index], deletes: [], updates: []))
return nil
}
}
Expand All @@ -73,7 +73,7 @@ extension ObservableCollectionType where Index: DictionaryIndexType, Collection
if let index = collection.indexForKey(key) {
var new = collection
let oldValue = new.removeValueForKey(key)
dispatch(ObservableCollectionEvent(collection: new, inserts: [], deletes: [index], updates: []))
next(ObservableCollectionEvent(collection: new, inserts: [], deletes: [index], updates: []))
return oldValue
} else {
return nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ extension ObservableCollectionType where Element: Hashable, Collection == Set<El
new.insert(member)

if let index = collection.indexOf(member) {
dispatch(ObservableCollectionEvent(collection: new, inserts: [], deletes: [], updates: [index]))
next(ObservableCollectionEvent(collection: new, inserts: [], deletes: [], updates: [index]))
} else {
dispatch(ObservableCollectionEvent(collection: new, inserts: [new.indexOf(member)!], deletes: [], updates: []))
next(ObservableCollectionEvent(collection: new, inserts: [new.indexOf(member)!], deletes: [], updates: []))
}
}

Expand All @@ -54,7 +54,7 @@ extension ObservableCollectionType where Element: Hashable, Collection == Set<El

if let index = collection.indexOf(member) {
let old = new.removeAtIndex(index)
dispatch(ObservableCollectionEvent(collection: new, inserts: [], deletes: [index], updates: []))
next(ObservableCollectionEvent(collection: new, inserts: [], deletes: [index], updates: []))
return old
} else {
return nil
Expand Down
78 changes: 30 additions & 48 deletions ReactiveKit/ObservableCollection/ObservableCollection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,44 +28,37 @@ public protocol ObservableCollectionType: CollectionType, StreamType {
typealias Element = Collection.Generator.Element

var collection: Collection { get }
mutating func dispatch(event: ObservableCollectionEvent<Collection>)
mutating func next(event: ObservableCollectionEvent<Collection>)

func observe(on context: ExecutionContext, observer: ObservableCollectionEvent<Collection> -> ()) -> DisposableType
func observe(on context: ExecutionContext?, observer: ObservableCollectionEvent<Collection> -> ()) -> DisposableType
}

public class ObservableCollection<Collection: CollectionType>: ActiveStream<ObservableCollectionEvent<Collection>>, ObservableCollectionType {

public private(set) var collection: Collection {
get {
return try! lastEvent().collection
}
set {
dispatch(ObservableCollectionEvent(collection: newValue, inserts: [], deletes: [], updates: []))
}
public final class ObservableCollection<Collection: CollectionType>: ActiveStream<ObservableCollectionEvent<Collection>>, ObservableCollectionType {

private var collectionEvent: ObservableCollectionEvent<Collection>! = nil

public var collection: Collection {
return collectionEvent.collection
}

private var capturedObserver: (ObservableCollectionEvent<Collection> -> ())? = nil

public convenience init(_ collection: Collection) {
var capturedObserver: (ObservableCollectionEvent<Collection> -> ())!

self.init() { observer in
capturedObserver = observer
observer(ObservableCollectionEvent.initial(collection))
return nil
}

self.capturedObserver = capturedObserver

public init(_ collection: Collection) {
collectionEvent = ObservableCollectionEvent.initial(collection)
super.init()
}

public init(@noescape producer: (ObservableCollectionEvent<Collection> -> ()) -> DisposableType?) {
super.init(limit: 1, producer: { observer in
return producer(observer)
})
public override init(@noescape producer: (ObservableCollectionEvent<Collection> -> ()) -> DisposableType?) {
super.init(producer: producer)
}

public func dispatch(event: ObservableCollectionEvent<Collection>) {
capturedObserver?(event)

public override func next(event: ObservableCollectionEvent<Collection>) {
collectionEvent = event
super.next(event)
}

public override func observe(on context: ExecutionContext? = ImmediateOnMainExecutionContext, observer: Observer) -> DisposableType {
let disposable = super.observe(on: context, observer: observer)
observer(collectionEvent)
return disposable
}

// MARK: CollectionType conformance
Expand Down Expand Up @@ -111,18 +104,7 @@ public extension ObservableCollectionType {
public mutating func replace(newCollection: Collection) {
let deletes = Array(collection.indices)
let inserts = Array(newCollection.indices)
dispatch(ObservableCollectionEvent(collection: newCollection, inserts: inserts, deletes: deletes, updates: []))
}

@warn_unused_result
public func zipPrevious() -> Observable<(ObservableCollectionEvent<Collection>?, ObservableCollectionEvent<Collection>)> {
return create { observer in
var previous: ObservableCollectionEvent<Collection>? = nil
return self.observe(on: ImmediateExecutionContext) { event in
observer(previous, event)
previous = event
}
}
next(ObservableCollectionEvent(collection: newCollection, inserts: inserts, deletes: deletes, updates: []))
}
}

Expand All @@ -132,7 +114,7 @@ public extension ObservableCollectionType where Collection.Index == Int {
@warn_unused_result
public func map<U>(transform: Collection.Generator.Element -> U) -> ObservableCollection<Array<U>> {
return create { observer in
return self.observe(on: ImmediateExecutionContext) { event in
return self.observe(on: nil) { event in
observer(event.map(transform))
}
}
Expand All @@ -142,7 +124,7 @@ public extension ObservableCollectionType where Collection.Index == Int {
@warn_unused_result
public func lazyMap<U>(transform: Collection.Generator.Element -> U) -> ObservableCollection<LazyMapCollection<Collection, U>> {
return create { observer in
return self.observe(on: ImmediateExecutionContext) { event in
return self.observe(on: nil) { event in
observer(event.lazyMap(transform))
}
}
Expand All @@ -155,7 +137,7 @@ public extension ObservableCollectionType where Collection.Index == Int {
@warn_unused_result
public func filter(include: Collection.Generator.Element -> Bool) -> ObservableCollection<Array<Collection.Generator.Element>> {
return create { observer in
return self.observe(on: ImmediateExecutionContext) { event in
return self.observe(on: nil) { event in
observer(event.filter(include))
}
}
Expand All @@ -168,7 +150,7 @@ public extension ObservableCollectionType where Collection.Index: Hashable {
@warn_unused_result
public func sort(isOrderedBefore: (Collection.Generator.Element, Collection.Generator.Element) -> Bool) -> ObservableCollection<Array<Collection.Generator.Element>> {
return create { observer in
return self.observe(on: ImmediateExecutionContext) { event in
return self.observe(on: nil) { event in
observer(event.sort(isOrderedBefore))
}
}
Expand All @@ -181,7 +163,7 @@ public extension ObservableCollectionType where Collection.Index: Equatable {
@warn_unused_result
public func sort(isOrderedBefore: (Collection.Generator.Element, Collection.Generator.Element) -> Bool) -> ObservableCollection<Array<Collection.Generator.Element>> {
return create { observer in
return self.observe(on: ImmediateExecutionContext) { event in
return self.observe(on: nil) { event in
observer(event.sort(isOrderedBefore))
}
}
Expand Down
Loading

0 comments on commit 924d114

Please sign in to comment.