From 924d114e466684347bd21679dddb36fc37705098 Mon Sep 17 00:00:00 2001 From: Srdan Rasic Date: Mon, 23 Nov 2015 10:44:03 +0100 Subject: [PATCH] Performance improvements --- ReactiveKit.podspec | 4 +- ReactiveKit.xcodeproj/project.pbxproj | 55 ++++++------ ReactiveKit/Info.plist | 2 +- .../Observable/MutableObservable.swift | 2 +- ReactiveKit/Observable/Observable.swift | 37 +++------ .../ObservableBuffer.swift} | 45 +++++----- .../MutableObservableCollection.swift | 6 +- .../ObservableCollection+Array.swift | 14 ++-- .../ObservableCollection+Dictionary.swift | 6 +- .../ObservableCollection+Set.swift | 6 +- .../ObservableCollection.swift | 78 +++++++---------- ReactiveKit/Operation/Operation.swift | 40 ++++----- ReactiveKit/Operation/Stream+Operation.swift | 12 +-- ReactiveKit/Other/TokenizedCollection.swift | 54 ------------ ReactiveKit/Streams/ActiveStream.swift | 83 +++++++++---------- ReactiveKit/Streams/Stream.swift | 16 +++- ReactiveKit/Streams/StreamType.swift | 44 +++++----- ReactiveKitTests/OperationSpec.swift | 24 +++--- ReactiveKitTests/PerformanceTests.swift | 56 +++++++++++++ 19 files changed, 279 insertions(+), 305 deletions(-) rename ReactiveKit/{Internals/StreamBuffer.swift => ObservableBuffer/ObservableBuffer.swift} (64%) delete mode 100644 ReactiveKit/Other/TokenizedCollection.swift create mode 100644 ReactiveKitTests/PerformanceTests.swift diff --git a/ReactiveKit.podspec b/ReactiveKit.podspec index e972c85..5aa8bac 100644 --- a/ReactiveKit.podspec +++ b/ReactiveKit.podspec @@ -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" => "srdan.rasic@gmail.com" } - 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' diff --git a/ReactiveKit.xcodeproj/project.pbxproj b/ReactiveKit.xcodeproj/project.pbxproj index fcdacfa..6e4515c 100644 --- a/ReactiveKit.xcodeproj/project.pbxproj +++ b/ReactiveKit.xcodeproj/project.pbxproj @@ -29,13 +29,11 @@ 16C33B3F1BEFBA2D00A0DBE0 /* SimpleDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDF01BEB6BBE00723476 /* SimpleDisposable.swift */; }; 16C33B401BEFBA2D00A0DBE0 /* Lock.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDF21BEB6BBE00723476 /* Lock.swift */; }; 16C33B411BEFBA2D00A0DBE0 /* Reference.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDF31BEB6BBE00723476 /* Reference.swift */; }; - 16C33B421BEFBA2D00A0DBE0 /* StreamBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDF41BEB6BBE00723476 /* StreamBuffer.swift */; }; 16C33B431BEFBA2D00A0DBE0 /* NoError.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE2A1BEB6BE100723476 /* NoError.swift */; }; 16C33B441BEFBA2D00A0DBE0 /* Bindable.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDFE1BEB6BBE00723476 /* Bindable.swift */; }; 16C33B451BEFBA2D00A0DBE0 /* ExecutionContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDFF1BEB6BBE00723476 /* ExecutionContext.swift */; }; 16C33B461BEFBA2D00A0DBE0 /* OptionalType.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE001BEB6BBE00723476 /* OptionalType.swift */; }; 16C33B471BEFBA2D00A0DBE0 /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE011BEB6BBE00723476 /* Queue.swift */; }; - 16C33B481BEFBA2D00A0DBE0 /* TokenizedCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE021BEB6BBE00723476 /* TokenizedCollection.swift */; }; 16C33B491BEFBA2D00A0DBE0 /* StreamType.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE061BEB6BBE00723476 /* StreamType.swift */; }; 16C33B4A1BEFBA2D00A0DBE0 /* Stream.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE051BEB6BBE00723476 /* Stream.swift */; }; 16C33B4B1BEFBA2D00A0DBE0 /* ActiveStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE041BEB6BBE00723476 /* ActiveStream.swift */; }; @@ -57,13 +55,11 @@ 16C33B5B1BEFBA2D00A0DBE0 /* SimpleDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDF01BEB6BBE00723476 /* SimpleDisposable.swift */; }; 16C33B5C1BEFBA2D00A0DBE0 /* Lock.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDF21BEB6BBE00723476 /* Lock.swift */; }; 16C33B5D1BEFBA2D00A0DBE0 /* Reference.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDF31BEB6BBE00723476 /* Reference.swift */; }; - 16C33B5E1BEFBA2D00A0DBE0 /* StreamBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDF41BEB6BBE00723476 /* StreamBuffer.swift */; }; 16C33B5F1BEFBA2D00A0DBE0 /* NoError.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE2A1BEB6BE100723476 /* NoError.swift */; }; 16C33B601BEFBA2D00A0DBE0 /* Bindable.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDFE1BEB6BBE00723476 /* Bindable.swift */; }; 16C33B611BEFBA2D00A0DBE0 /* ExecutionContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDFF1BEB6BBE00723476 /* ExecutionContext.swift */; }; 16C33B621BEFBA2D00A0DBE0 /* OptionalType.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE001BEB6BBE00723476 /* OptionalType.swift */; }; 16C33B631BEFBA2D00A0DBE0 /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE011BEB6BBE00723476 /* Queue.swift */; }; - 16C33B641BEFBA2D00A0DBE0 /* TokenizedCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE021BEB6BBE00723476 /* TokenizedCollection.swift */; }; 16C33B651BEFBA2E00A0DBE0 /* StreamType.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE061BEB6BBE00723476 /* StreamType.swift */; }; 16C33B661BEFBA2E00A0DBE0 /* Stream.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE051BEB6BBE00723476 /* Stream.swift */; }; 16C33B671BEFBA2E00A0DBE0 /* ActiveStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE041BEB6BBE00723476 /* ActiveStream.swift */; }; @@ -85,17 +81,14 @@ 16C33B771BEFBA2E00A0DBE0 /* SimpleDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDF01BEB6BBE00723476 /* SimpleDisposable.swift */; }; 16C33B781BEFBA2E00A0DBE0 /* Lock.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDF21BEB6BBE00723476 /* Lock.swift */; }; 16C33B791BEFBA2E00A0DBE0 /* Reference.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDF31BEB6BBE00723476 /* Reference.swift */; }; - 16C33B7A1BEFBA2E00A0DBE0 /* StreamBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDF41BEB6BBE00723476 /* StreamBuffer.swift */; }; 16C33B7B1BEFBA2E00A0DBE0 /* NoError.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE2A1BEB6BE100723476 /* NoError.swift */; }; 16C33B7C1BEFBA2E00A0DBE0 /* Bindable.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDFE1BEB6BBE00723476 /* Bindable.swift */; }; 16C33B7D1BEFBA2E00A0DBE0 /* ExecutionContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDFF1BEB6BBE00723476 /* ExecutionContext.swift */; }; 16C33B7E1BEFBA2E00A0DBE0 /* OptionalType.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE001BEB6BBE00723476 /* OptionalType.swift */; }; 16C33B7F1BEFBA2E00A0DBE0 /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE011BEB6BBE00723476 /* Queue.swift */; }; - 16C33B801BEFBA2E00A0DBE0 /* TokenizedCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE021BEB6BBE00723476 /* TokenizedCollection.swift */; }; 16C33B831BEFBAC800A0DBE0 /* ReactiveKit.h in Headers */ = {isa = PBXBuildFile; fileRef = ECBCCDD31BEB6B9A00723476 /* ReactiveKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 16C33B841BEFBAC900A0DBE0 /* ReactiveKit.h in Headers */ = {isa = PBXBuildFile; fileRef = ECBCCDD31BEB6B9A00723476 /* ReactiveKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 16C33B851BEFBAC900A0DBE0 /* ReactiveKit.h in Headers */ = {isa = PBXBuildFile; fileRef = ECBCCDD31BEB6B9A00723476 /* ReactiveKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 16EABAD01C01AD82008B20BD /* ObservableCollectionSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 16EABACF1C01AD82008B20BD /* ObservableCollectionSpec.swift */; }; 16F0B8761BEFC3850071847A /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 16F0B8751BEFC3850071847A /* Quick.framework */; }; 16F0B8781BEFC3890071847A /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 16F0B8771BEFC3890071847A /* Nimble.framework */; }; EC0DF29A1BF48FF400DFF3E6 /* MutableObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0DF2991BF48FF400DFF3E6 /* MutableObservable.swift */; }; @@ -106,13 +99,19 @@ EC0DF2A01BF4909C00DFF3E6 /* MutableObservableCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0DF29E1BF4909C00DFF3E6 /* MutableObservableCollection.swift */; }; EC0DF2A11BF4909C00DFF3E6 /* MutableObservableCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0DF29E1BF4909C00DFF3E6 /* MutableObservableCollection.swift */; }; EC0DF2A21BF4909C00DFF3E6 /* MutableObservableCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0DF29E1BF4909C00DFF3E6 /* MutableObservableCollection.swift */; }; - EC835BE21BEC923400463098 /* OperationSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC835BE11BEC923400463098 /* OperationSpec.swift */; }; + EC2C7A0D1C02ED71006BFEE1 /* PerformanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC2C7A0C1C02ED71006BFEE1 /* PerformanceTests.swift */; }; + EC2C7A421C031030006BFEE1 /* ObservableBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC2C7A411C031030006BFEE1 /* ObservableBuffer.swift */; }; + EC2C7A431C031030006BFEE1 /* ObservableBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC2C7A411C031030006BFEE1 /* ObservableBuffer.swift */; }; + EC2C7A441C031030006BFEE1 /* ObservableBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC2C7A411C031030006BFEE1 /* ObservableBuffer.swift */; }; + EC2C7A451C031030006BFEE1 /* ObservableBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC2C7A411C031030006BFEE1 /* ObservableBuffer.swift */; }; + EC2C7A461C0314BC006BFEE1 /* StreamSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDDF1BEB6B9B00723476 /* StreamSpec.swift */; }; + EC2C7A471C0314BC006BFEE1 /* OperationSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC835BE11BEC923400463098 /* OperationSpec.swift */; }; + EC2C7A481C0314BC006BFEE1 /* ObservableCollectionSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 16EABACF1C01AD82008B20BD /* ObservableCollectionSpec.swift */; }; EC9549B31BF1EFA2000FC2BF /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1648A99E1BF12CE9007A185C /* Result.swift */; }; EC9549B41BF1EFA3000FC2BF /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1648A99E1BF12CE9007A185C /* Result.swift */; }; EC9549B51BF1EFA4000FC2BF /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1648A99E1BF12CE9007A185C /* Result.swift */; }; ECBCCDD41BEB6B9A00723476 /* ReactiveKit.h in Headers */ = {isa = PBXBuildFile; fileRef = ECBCCDD31BEB6B9A00723476 /* ReactiveKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; ECBCCDDB1BEB6B9B00723476 /* ReactiveKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ECBCCDD01BEB6B9A00723476 /* ReactiveKit.framework */; }; - ECBCCDE01BEB6B9B00723476 /* StreamSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDDF1BEB6B9B00723476 /* StreamSpec.swift */; }; ECBCCE0D1BEB6BBE00723476 /* BlockDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDEB1BEB6BBE00723476 /* BlockDisposable.swift */; }; ECBCCE0E1BEB6BBE00723476 /* CompositeDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDEC1BEB6BBE00723476 /* CompositeDisposable.swift */; }; ECBCCE0F1BEB6BBE00723476 /* Disposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDED1BEB6BBE00723476 /* Disposable.swift */; }; @@ -121,7 +120,6 @@ ECBCCE121BEB6BBE00723476 /* SimpleDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDF01BEB6BBE00723476 /* SimpleDisposable.swift */; }; ECBCCE131BEB6BBE00723476 /* Lock.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDF21BEB6BBE00723476 /* Lock.swift */; }; ECBCCE141BEB6BBE00723476 /* Reference.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDF31BEB6BBE00723476 /* Reference.swift */; }; - ECBCCE151BEB6BBE00723476 /* StreamBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDF41BEB6BBE00723476 /* StreamBuffer.swift */; }; ECBCCE161BEB6BBE00723476 /* Observable.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDF61BEB6BBE00723476 /* Observable.swift */; }; ECBCCE171BEB6BBE00723476 /* ObservableCollection+Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDF81BEB6BBE00723476 /* ObservableCollection+Array.swift */; }; ECBCCE181BEB6BBE00723476 /* ObservableCollection+Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDF91BEB6BBE00723476 /* ObservableCollection+Dictionary.swift */; }; @@ -132,7 +130,6 @@ ECBCCE1D1BEB6BBE00723476 /* ExecutionContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCDFF1BEB6BBE00723476 /* ExecutionContext.swift */; }; ECBCCE1E1BEB6BBE00723476 /* OptionalType.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE001BEB6BBE00723476 /* OptionalType.swift */; }; ECBCCE1F1BEB6BBE00723476 /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE011BEB6BBE00723476 /* Queue.swift */; }; - ECBCCE201BEB6BBE00723476 /* TokenizedCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE021BEB6BBE00723476 /* TokenizedCollection.swift */; }; ECBCCE211BEB6BBE00723476 /* ActiveStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE041BEB6BBE00723476 /* ActiveStream.swift */; }; ECBCCE221BEB6BBE00723476 /* Stream.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE051BEB6BBE00723476 /* Stream.swift */; }; ECBCCE231BEB6BBE00723476 /* StreamType.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBCCE061BEB6BBE00723476 /* StreamType.swift */; }; @@ -165,6 +162,8 @@ 16F0B8771BEFC3890071847A /* Nimble.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Nimble.framework; path = "../Carthage/Checkouts/Nimble/build/Debug-iphoneos/Nimble.framework"; sourceTree = ""; }; EC0DF2991BF48FF400DFF3E6 /* MutableObservable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MutableObservable.swift; sourceTree = ""; }; EC0DF29E1BF4909C00DFF3E6 /* MutableObservableCollection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MutableObservableCollection.swift; sourceTree = ""; }; + EC2C7A0C1C02ED71006BFEE1 /* PerformanceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PerformanceTests.swift; sourceTree = ""; }; + EC2C7A411C031030006BFEE1 /* ObservableBuffer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ObservableBuffer.swift; path = ReactiveKit/ObservableBuffer/ObservableBuffer.swift; sourceTree = SOURCE_ROOT; }; EC835BE11BEC923400463098 /* OperationSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperationSpec.swift; sourceTree = ""; }; EC835C001BECB0FB00463098 /* ReactiveKitPlayground.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = ReactiveKitPlayground.playground; sourceTree = SOURCE_ROOT; }; ECBCCDD01BEB6B9A00723476 /* ReactiveKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ReactiveKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -181,7 +180,6 @@ ECBCCDF01BEB6BBE00723476 /* SimpleDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SimpleDisposable.swift; sourceTree = ""; }; ECBCCDF21BEB6BBE00723476 /* Lock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Lock.swift; sourceTree = ""; }; ECBCCDF31BEB6BBE00723476 /* Reference.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Reference.swift; sourceTree = ""; }; - ECBCCDF41BEB6BBE00723476 /* StreamBuffer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StreamBuffer.swift; sourceTree = ""; }; ECBCCDF61BEB6BBE00723476 /* Observable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Observable.swift; sourceTree = ""; }; ECBCCDF81BEB6BBE00723476 /* ObservableCollection+Array.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ObservableCollection+Array.swift"; sourceTree = ""; }; ECBCCDF91BEB6BBE00723476 /* ObservableCollection+Dictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ObservableCollection+Dictionary.swift"; sourceTree = ""; }; @@ -192,7 +190,6 @@ ECBCCDFF1BEB6BBE00723476 /* ExecutionContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExecutionContext.swift; sourceTree = ""; }; ECBCCE001BEB6BBE00723476 /* OptionalType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OptionalType.swift; sourceTree = ""; }; ECBCCE011BEB6BBE00723476 /* Queue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Queue.swift; sourceTree = ""; }; - ECBCCE021BEB6BBE00723476 /* TokenizedCollection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TokenizedCollection.swift; sourceTree = ""; }; ECBCCE041BEB6BBE00723476 /* ActiveStream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActiveStream.swift; sourceTree = ""; }; ECBCCE051BEB6BBE00723476 /* Stream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stream.swift; sourceTree = ""; }; ECBCCE061BEB6BBE00723476 /* StreamType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StreamType.swift; sourceTree = ""; }; @@ -254,6 +251,15 @@ name = Dependencies; sourceTree = ""; }; + EC2C7A401C031006006BFEE1 /* ObservableBuffer */ = { + isa = PBXGroup; + children = ( + EC2C7A411C031030006BFEE1 /* ObservableBuffer.swift */, + ); + name = ObservableBuffer; + path = ObservableCollection; + sourceTree = ""; + }; EC835BF21BECB0D500463098 /* Playgrounds */ = { isa = PBXGroup; children = ( @@ -296,6 +302,7 @@ ECBCCE291BEB6BE100723476 /* Operation */, ECBCCDF51BEB6BBE00723476 /* Observable */, ECBCCDF71BEB6BBE00723476 /* ObservableCollection */, + EC2C7A401C031006006BFEE1 /* ObservableBuffer */, ECBCCDEA1BEB6BBE00723476 /* Disposables */, ECBCCDF11BEB6BBE00723476 /* Internals */, ECBCCDFD1BEB6BBE00723476 /* Other */, @@ -309,6 +316,7 @@ ECBCCDDF1BEB6B9B00723476 /* StreamSpec.swift */, EC835BE11BEC923400463098 /* OperationSpec.swift */, 16EABACF1C01AD82008B20BD /* ObservableCollectionSpec.swift */, + EC2C7A0C1C02ED71006BFEE1 /* PerformanceTests.swift */, 16F0B8791BEFC3A10071847A /* Dependencies */, ECBCCDE11BEB6B9B00723476 /* Info.plist */, ); @@ -333,7 +341,6 @@ children = ( ECBCCDF21BEB6BBE00723476 /* Lock.swift */, ECBCCDF31BEB6BBE00723476 /* Reference.swift */, - ECBCCDF41BEB6BBE00723476 /* StreamBuffer.swift */, ); path = Internals; sourceTree = ""; @@ -368,7 +375,6 @@ ECBCCE001BEB6BBE00723476 /* OptionalType.swift */, ECBCCE011BEB6BBE00723476 /* Queue.swift */, ECBCCDFF1BEB6BBE00723476 /* ExecutionContext.swift */, - ECBCCE021BEB6BBE00723476 /* TokenizedCollection.swift */, 1648A99E1BF12CE9007A185C /* Result.swift */, ); path = Other; @@ -620,7 +626,6 @@ 16C33B361BEFBA2D00A0DBE0 /* ObservableCollection+Dictionary.swift in Sources */, 16C33B341BEFBA2D00A0DBE0 /* Observable.swift in Sources */, 16C33B331BEFBA2D00A0DBE0 /* Stream+Operation.swift in Sources */, - 16C33B421BEFBA2D00A0DBE0 /* StreamBuffer.swift in Sources */, EC0DF29B1BF48FF400DFF3E6 /* MutableObservable.swift in Sources */, 16C33B431BEFBA2D00A0DBE0 /* NoError.swift in Sources */, 16C33B321BEFBA2D00A0DBE0 /* OperationSink.swift in Sources */, @@ -630,13 +635,13 @@ 16C33B391BEFBA2D00A0DBE0 /* ObservableCollectionEvent.swift in Sources */, 16C33B411BEFBA2D00A0DBE0 /* Reference.swift in Sources */, 16C33B2D1BEFBA2D00A0DBE0 /* StreamType.swift in Sources */, + EC2C7A431C031030006BFEE1 /* ObservableBuffer.swift in Sources */, 16C33B381BEFBA2D00A0DBE0 /* ObservableCollection.swift in Sources */, 16C33B471BEFBA2D00A0DBE0 /* Queue.swift in Sources */, 16C33B2E1BEFBA2D00A0DBE0 /* Stream.swift in Sources */, 16C33B3E1BEFBA2D00A0DBE0 /* SerialDisposable.swift in Sources */, 16C33B371BEFBA2D00A0DBE0 /* ObservableCollection+Set.swift in Sources */, 16C33B311BEFBA2D00A0DBE0 /* OperationEvent.swift in Sources */, - 16C33B481BEFBA2D00A0DBE0 /* TokenizedCollection.swift in Sources */, 16C33B3F1BEFBA2D00A0DBE0 /* SimpleDisposable.swift in Sources */, 16C33B301BEFBA2D00A0DBE0 /* Operation.swift in Sources */, EC0DF2A01BF4909C00DFF3E6 /* MutableObservableCollection.swift in Sources */, @@ -658,7 +663,6 @@ 16C33B521BEFBA2D00A0DBE0 /* ObservableCollection+Dictionary.swift in Sources */, 16C33B501BEFBA2D00A0DBE0 /* Observable.swift in Sources */, 16C33B4F1BEFBA2D00A0DBE0 /* Stream+Operation.swift in Sources */, - 16C33B5E1BEFBA2D00A0DBE0 /* StreamBuffer.swift in Sources */, EC0DF29C1BF48FF400DFF3E6 /* MutableObservable.swift in Sources */, 16C33B5F1BEFBA2D00A0DBE0 /* NoError.swift in Sources */, 16C33B4E1BEFBA2D00A0DBE0 /* OperationSink.swift in Sources */, @@ -668,13 +672,13 @@ 16C33B551BEFBA2D00A0DBE0 /* ObservableCollectionEvent.swift in Sources */, 16C33B5D1BEFBA2D00A0DBE0 /* Reference.swift in Sources */, 16C33B491BEFBA2D00A0DBE0 /* StreamType.swift in Sources */, + EC2C7A441C031030006BFEE1 /* ObservableBuffer.swift in Sources */, 16C33B541BEFBA2D00A0DBE0 /* ObservableCollection.swift in Sources */, 16C33B631BEFBA2D00A0DBE0 /* Queue.swift in Sources */, 16C33B4A1BEFBA2D00A0DBE0 /* Stream.swift in Sources */, 16C33B5A1BEFBA2D00A0DBE0 /* SerialDisposable.swift in Sources */, 16C33B531BEFBA2D00A0DBE0 /* ObservableCollection+Set.swift in Sources */, 16C33B4D1BEFBA2D00A0DBE0 /* OperationEvent.swift in Sources */, - 16C33B641BEFBA2D00A0DBE0 /* TokenizedCollection.swift in Sources */, 16C33B5B1BEFBA2D00A0DBE0 /* SimpleDisposable.swift in Sources */, 16C33B4C1BEFBA2D00A0DBE0 /* Operation.swift in Sources */, EC0DF2A11BF4909C00DFF3E6 /* MutableObservableCollection.swift in Sources */, @@ -696,7 +700,6 @@ 16C33B6E1BEFBA2E00A0DBE0 /* ObservableCollection+Dictionary.swift in Sources */, 16C33B6C1BEFBA2E00A0DBE0 /* Observable.swift in Sources */, 16C33B6B1BEFBA2E00A0DBE0 /* Stream+Operation.swift in Sources */, - 16C33B7A1BEFBA2E00A0DBE0 /* StreamBuffer.swift in Sources */, EC0DF29D1BF48FF400DFF3E6 /* MutableObservable.swift in Sources */, 16C33B7B1BEFBA2E00A0DBE0 /* NoError.swift in Sources */, 16C33B6A1BEFBA2E00A0DBE0 /* OperationSink.swift in Sources */, @@ -706,13 +709,13 @@ 16C33B711BEFBA2E00A0DBE0 /* ObservableCollectionEvent.swift in Sources */, 16C33B791BEFBA2E00A0DBE0 /* Reference.swift in Sources */, 16C33B651BEFBA2E00A0DBE0 /* StreamType.swift in Sources */, + EC2C7A451C031030006BFEE1 /* ObservableBuffer.swift in Sources */, 16C33B701BEFBA2E00A0DBE0 /* ObservableCollection.swift in Sources */, 16C33B7F1BEFBA2E00A0DBE0 /* Queue.swift in Sources */, 16C33B661BEFBA2E00A0DBE0 /* Stream.swift in Sources */, 16C33B761BEFBA2E00A0DBE0 /* SerialDisposable.swift in Sources */, 16C33B6F1BEFBA2E00A0DBE0 /* ObservableCollection+Set.swift in Sources */, 16C33B691BEFBA2E00A0DBE0 /* OperationEvent.swift in Sources */, - 16C33B801BEFBA2E00A0DBE0 /* TokenizedCollection.swift in Sources */, 16C33B771BEFBA2E00A0DBE0 /* SimpleDisposable.swift in Sources */, 16C33B681BEFBA2E00A0DBE0 /* Operation.swift in Sources */, EC0DF2A21BF4909C00DFF3E6 /* MutableObservableCollection.swift in Sources */, @@ -729,9 +732,7 @@ buildActionMask = 2147483647; files = ( ECBCCE1B1BEB6BBE00723476 /* ObservableCollectionEvent.swift in Sources */, - ECBCCE201BEB6BBE00723476 /* TokenizedCollection.swift in Sources */, ECBCCE301BEB6BE100723476 /* Stream+Operation.swift in Sources */, - ECBCCE151BEB6BBE00723476 /* StreamBuffer.swift in Sources */, ECBCCE211BEB6BBE00723476 /* ActiveStream.swift in Sources */, ECBCCE101BEB6BBE00723476 /* DisposeBag.swift in Sources */, ECBCCE1F1BEB6BBE00723476 /* Queue.swift in Sources */, @@ -744,6 +745,7 @@ ECBCCE231BEB6BBE00723476 /* StreamType.swift in Sources */, ECBCCE141BEB6BBE00723476 /* Reference.swift in Sources */, ECBCCE0D1BEB6BBE00723476 /* BlockDisposable.swift in Sources */, + EC2C7A421C031030006BFEE1 /* ObservableBuffer.swift in Sources */, ECBCCE221BEB6BBE00723476 /* Stream.swift in Sources */, ECBCCE0F1BEB6BBE00723476 /* Disposable.swift in Sources */, ECBCCE131BEB6BBE00723476 /* Lock.swift in Sources */, @@ -766,9 +768,10 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 16EABAD01C01AD82008B20BD /* ObservableCollectionSpec.swift in Sources */, - EC835BE21BEC923400463098 /* OperationSpec.swift in Sources */, - ECBCCDE01BEB6B9B00723476 /* StreamSpec.swift in Sources */, + EC2C7A461C0314BC006BFEE1 /* StreamSpec.swift in Sources */, + EC2C7A481C0314BC006BFEE1 /* ObservableCollectionSpec.swift in Sources */, + EC2C7A471C0314BC006BFEE1 /* OperationSpec.swift in Sources */, + EC2C7A0D1C02ED71006BFEE1 /* PerformanceTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ReactiveKit/Info.plist b/ReactiveKit/Info.plist index 5e4e25b..61718cd 100644 --- a/ReactiveKit/Info.plist +++ b/ReactiveKit/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0.5 + 1.0.6 CFBundleSignature ???? CFBundleVersion diff --git a/ReactiveKit/Observable/MutableObservable.swift b/ReactiveKit/Observable/MutableObservable.swift index 8e9a696..da05497 100644 --- a/ReactiveKit/Observable/MutableObservable.swift +++ b/ReactiveKit/Observable/MutableObservable.swift @@ -39,7 +39,7 @@ public struct MutableObservable: 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) } } diff --git a/ReactiveKit/Observable/Observable.swift b/ReactiveKit/Observable/Observable.swift index aff110b..1ffc28d 100644 --- a/ReactiveKit/Observable/Observable.swift +++ b/ReactiveKit/Observable/Observable.swift @@ -27,37 +27,22 @@ public protocol ObservableType: StreamType { var value: Value { get set } } -public class Observable: ActiveStream, ObservableType { +public final class Observable: ActiveStream, 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(producer: (Value -> ()) -> DisposableType?) -> Observable { - 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 + } } diff --git a/ReactiveKit/Internals/StreamBuffer.swift b/ReactiveKit/ObservableBuffer/ObservableBuffer.swift similarity index 64% rename from ReactiveKit/Internals/StreamBuffer.swift rename to ReactiveKit/ObservableBuffer/ObservableBuffer.swift index 0608d88..56e8ded 100644 --- a/ReactiveKit/Internals/StreamBuffer.swift +++ b/ReactiveKit/ObservableBuffer/ObservableBuffer.swift @@ -22,37 +22,34 @@ // THE SOFTWARE. // -public class StreamBuffer { - - public var array: [Event] = [] +public final class ObservableBuffer: ActiveStream { + + 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 -} diff --git a/ReactiveKit/ObservableCollection/MutableObservableCollection.swift b/ReactiveKit/ObservableCollection/MutableObservableCollection.swift index 9e83d5c..d835f19 100644 --- a/ReactiveKit/ObservableCollection/MutableObservableCollection.swift +++ b/ReactiveKit/ObservableCollection/MutableObservableCollection.swift @@ -36,11 +36,11 @@ public struct MutableObservableCollection: Observabl observableCollection = ObservableCollection(collection) } - public mutating func dispatch(event: ObservableCollectionEvent) { - observableCollection.dispatch(event) + public mutating func next(event: ObservableCollectionEvent) { + observableCollection.next(event) } - public func observe(on context: ExecutionContext, observer: ObservableCollectionEvent -> ()) -> DisposableType { + public func observe(on context: ExecutionContext? = ImmediateOnMainExecutionContext, observer: ObservableCollectionEvent -> ()) -> DisposableType { return observableCollection.observe(on: context, observer: observer) } diff --git a/ReactiveKit/ObservableCollection/ObservableCollection+Array.swift b/ReactiveKit/ObservableCollection/ObservableCollection+Array.swift index 62ad07d..d3d6db4 100644 --- a/ReactiveKit/ObservableCollection/ObservableCollection+Array.swift +++ b/ReactiveKit/ObservableCollection/ObservableCollection+Array.swift @@ -27,38 +27,38 @@ extension ObservableCollectionType where Collection == Array { 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.. 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.Generator.Element { @@ -68,7 +68,7 @@ extension ObservableCollectionType where Collection == Array { set { var new = collection new[index] = newValue - dispatch(ObservableCollectionEvent(collection: new, inserts: [], deletes: [], updates: [index])) + next(ObservableCollectionEvent(collection: new, inserts: [], deletes: [], updates: [index])) } } } diff --git a/ReactiveKit/ObservableCollection/ObservableCollection+Dictionary.swift b/ReactiveKit/ObservableCollection/ObservableCollection+Dictionary.swift index 44b819f..36f35d2 100644 --- a/ReactiveKit/ObservableCollection/ObservableCollection+Dictionary.swift +++ b/ReactiveKit/ObservableCollection/ObservableCollection+Dictionary.swift @@ -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 } } @@ -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 diff --git a/ReactiveKit/ObservableCollection/ObservableCollection+Set.swift b/ReactiveKit/ObservableCollection/ObservableCollection+Set.swift index c9d5b00..05c01a4 100644 --- a/ReactiveKit/ObservableCollection/ObservableCollection+Set.swift +++ b/ReactiveKit/ObservableCollection/ObservableCollection+Set.swift @@ -43,9 +43,9 @@ extension ObservableCollectionType where Element: Hashable, Collection == Set) + mutating func next(event: ObservableCollectionEvent) - func observe(on context: ExecutionContext, observer: ObservableCollectionEvent -> ()) -> DisposableType + func observe(on context: ExecutionContext?, observer: ObservableCollectionEvent -> ()) -> DisposableType } -public class ObservableCollection: ActiveStream>, ObservableCollectionType { - - public private(set) var collection: Collection { - get { - return try! lastEvent().collection - } - set { - dispatch(ObservableCollectionEvent(collection: newValue, inserts: [], deletes: [], updates: [])) - } +public final class ObservableCollection: ActiveStream>, ObservableCollectionType { + + private var collectionEvent: ObservableCollectionEvent! = nil + + public var collection: Collection { + return collectionEvent.collection } - - private var capturedObserver: (ObservableCollectionEvent -> ())? = nil - - public convenience init(_ collection: Collection) { - var capturedObserver: (ObservableCollectionEvent -> ())! - - 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 -> ()) -> DisposableType?) { - super.init(limit: 1, producer: { observer in - return producer(observer) - }) + public override init(@noescape producer: (ObservableCollectionEvent -> ()) -> DisposableType?) { + super.init(producer: producer) } - - public func dispatch(event: ObservableCollectionEvent) { - capturedObserver?(event) + + public override func next(event: ObservableCollectionEvent) { + 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 @@ -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?, ObservableCollectionEvent)> { - return create { observer in - var previous: ObservableCollectionEvent? = nil - return self.observe(on: ImmediateExecutionContext) { event in - observer(previous, event) - previous = event - } - } + next(ObservableCollectionEvent(collection: newCollection, inserts: inserts, deletes: deletes, updates: [])) } } @@ -132,7 +114,7 @@ public extension ObservableCollectionType where Collection.Index == Int { @warn_unused_result public func map(transform: Collection.Generator.Element -> U) -> ObservableCollection> { return create { observer in - return self.observe(on: ImmediateExecutionContext) { event in + return self.observe(on: nil) { event in observer(event.map(transform)) } } @@ -142,7 +124,7 @@ public extension ObservableCollectionType where Collection.Index == Int { @warn_unused_result public func lazyMap(transform: Collection.Generator.Element -> U) -> ObservableCollection> { return create { observer in - return self.observe(on: ImmediateExecutionContext) { event in + return self.observe(on: nil) { event in observer(event.lazyMap(transform)) } } @@ -155,7 +137,7 @@ public extension ObservableCollectionType where Collection.Index == Int { @warn_unused_result public func filter(include: Collection.Generator.Element -> Bool) -> ObservableCollection> { return create { observer in - return self.observe(on: ImmediateExecutionContext) { event in + return self.observe(on: nil) { event in observer(event.filter(include)) } } @@ -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> { return create { observer in - return self.observe(on: ImmediateExecutionContext) { event in + return self.observe(on: nil) { event in observer(event.sort(isOrderedBefore)) } } @@ -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> { return create { observer in - return self.observe(on: ImmediateExecutionContext) { event in + return self.observe(on: nil) { event in observer(event.sort(isOrderedBefore)) } } diff --git a/ReactiveKit/Operation/Operation.swift b/ReactiveKit/Operation/Operation.swift index b5c7d33..eb3dc17 100644 --- a/ReactiveKit/Operation/Operation.swift +++ b/ReactiveKit/Operation/Operation.swift @@ -27,7 +27,7 @@ public protocol OperationType: StreamType { typealias Error: ErrorType func lift(transform: Stream> -> Stream>) -> Operation - func observe(on context: ExecutionContext, observer: OperationEvent -> ()) -> DisposableType + func observe(on context: ExecutionContext?, observer: OperationEvent -> ()) -> DisposableType } public struct Operation: OperationType { @@ -47,7 +47,7 @@ public struct Operation: OperationType { } } - public func observe(on context: ExecutionContext = ImmediateOnMainExecutionContext, observer: OperationEvent -> ()) -> DisposableType { + public func observe(on context: ExecutionContext? = ImmediateOnMainExecutionContext, observer: OperationEvent -> ()) -> DisposableType { return stream.observe(on: context, observer: observer) } @@ -68,7 +68,7 @@ public struct Operation: OperationType { public func lift(transform: Stream> -> Stream>) -> Operation { return create { observer in - return transform(self.stream).observe(on: ImmediateExecutionContext, observer: observer.observer) + return transform(self.stream).observe(on: nil, observer: observer.observer) } } } @@ -82,7 +82,7 @@ public func create(producer producer: OperationObserver public extension OperationType { - public func on(next next: (Value -> ())? = nil, success: (() -> ())? = nil, failure: (Error -> ())? = nil, start: (() -> Void)? = nil, completed: (() -> Void)? = nil, context: ExecutionContext = ImmediateExecutionContext) -> Operation { + public func on(next next: (Value -> ())? = nil, success: (() -> ())? = nil, failure: (Error -> ())? = nil, start: (() -> Void)? = nil, completed: (() -> Void)? = nil, context: ExecutionContext? = ImmediateOnMainExecutionContext) -> Operation { return create { observer in start?() return self.observe(on: context) { event in @@ -123,12 +123,12 @@ public extension OperationType { } @warn_unused_result - public func shareNext(limit: Int = Int.max, context: ExecutionContext = ImmediateOnMainExecutionContext) -> ActiveStream { - return create(limit) { observer in + public func shareNext(limit: Int = Int.max, context: ExecutionContext = ImmediateOnMainExecutionContext) -> ObservableBuffer { + return ObservableBuffer(limit: limit) { observer in return self.observeNext(on: context, observer: observer) } } - + @warn_unused_result public func map(transform: Value -> U) -> Operation { return lift { $0.map { $0.map(transform) } } @@ -193,7 +193,7 @@ public extension OperationType { attempt = { serialDisposable.otherDisposable?.dispose() - serialDisposable.otherDisposable = self.observe(on: ImmediateExecutionContext) { event in + serialDisposable.otherDisposable = self.observe(on: nil) { event in switch event { case .Failure(let error): if count > 0 { @@ -251,7 +251,7 @@ public extension OperationType { } } - let selfDisposable = self.observe(on: ImmediateExecutionContext) { event in + let selfDisposable = self.observe(on: nil) { event in if case .Failure(let error) = event { observer.failure(error) } else { @@ -262,7 +262,7 @@ public extension OperationType { } } - let otherDisposable = other.observe(on: ImmediateExecutionContext) { event in + let otherDisposable = other.observe(on: nil) { event in if case .Failure(let error) = event { observer.failure(error) } else { @@ -299,7 +299,7 @@ public extension OperationType { } } - let selfDisposable = self.observe(on: ImmediateExecutionContext) { event in + let selfDisposable = self.observe(on: nil) { event in switch event { case .Failure(let error): observer.failure(error) @@ -316,7 +316,7 @@ public extension OperationType { } } - let otherDisposable = other.observe(on: ImmediateExecutionContext) { event in + let otherDisposable = other.observe(on: nil) { event in switch event { case .Failure(let error): observer.failure(error) @@ -365,7 +365,7 @@ public extension OperationType where Value: OperationType, Value.Error == Error } } - compositeDisposable += self.observe(on: ImmediateExecutionContext) { taskEvent in + compositeDisposable += self.observe(on: nil) { taskEvent in switch taskEvent { case .Failure(let error): @@ -376,7 +376,7 @@ public extension OperationType where Value: OperationType, Value.Error == Error queue.sync { numberOfOperations += 1 } - compositeDisposable += task.observe(on: ImmediateExecutionContext) { event in + compositeDisposable += task.observe(on: nil) { event in switch event { case .Next, .Failure: observer.observer(event) @@ -399,7 +399,7 @@ public extension OperationType where Value: OperationType, Value.Error == Error var outerCompleted: Bool = false var innerCompleted: Bool = false - compositeDisposable += self.observe(on: ImmediateExecutionContext) { taskEvent in + compositeDisposable += self.observe(on: nil) { taskEvent in switch taskEvent { case .Failure(let error): @@ -412,7 +412,7 @@ public extension OperationType where Value: OperationType, Value.Error == Error case .Next(let innerOperation): innerCompleted = false serialDisposable.otherDisposable?.dispose() - serialDisposable.otherDisposable = innerOperation.observe(on: ImmediateExecutionContext) { event in + serialDisposable.otherDisposable = innerOperation.observe(on: nil) { event in switch event { case .Failure(let error): @@ -455,7 +455,7 @@ public extension OperationType where Value: OperationType, Value.Error == Error } serialDisposable.otherDisposable?.dispose() - serialDisposable.otherDisposable = task.observe(on: ImmediateExecutionContext) { event in + serialDisposable.otherDisposable = task.observe(on: nil) { event in switch event { case .Failure(let error): observer.failure(error) @@ -482,7 +482,7 @@ public extension OperationType where Value: OperationType, Value.Error == Error } } - compositeDisposable += self.observe(on: ImmediateExecutionContext) { taskEvent in + compositeDisposable += self.observe(on: nil) { taskEvent in switch taskEvent { case .Failure(let error): @@ -527,14 +527,14 @@ public extension OperationType { return create { observer in let serialDisposable = SerialDisposable(otherDisposable: nil) - serialDisposable.otherDisposable = self.observe(on: ImmediateExecutionContext) { taskEvent in + serialDisposable.otherDisposable = self.observe(on: nil) { taskEvent in switch taskEvent { case .Next(let value): observer.next(value) case .Success: observer.success() case .Failure(let error): - serialDisposable.otherDisposable = recover(error).observe(on: ImmediateExecutionContext) { event in + serialDisposable.otherDisposable = recover(error).observe(on: nil) { event in observer.observer(event) } } diff --git a/ReactiveKit/Operation/Stream+Operation.swift b/ReactiveKit/Operation/Stream+Operation.swift index 6c844d3..8f31ed9 100644 --- a/ReactiveKit/Operation/Stream+Operation.swift +++ b/ReactiveKit/Operation/Stream+Operation.swift @@ -29,8 +29,8 @@ public extension StreamType where Event: OperationType { return create { observer in let compositeDisposable = CompositeDisposable() - compositeDisposable += self.observe(on: ImmediateExecutionContext) { task in - compositeDisposable += task.observe(on: ImmediateExecutionContext) { event in + compositeDisposable += self.observe(on: nil) { task in + compositeDisposable += task.observe(on: nil) { event in switch event { case .Next, .Failure: observer.observer(event) @@ -49,10 +49,10 @@ public extension StreamType where Event: OperationType { let serialDisposable = SerialDisposable(otherDisposable: nil) let compositeDisposable = CompositeDisposable([serialDisposable]) - compositeDisposable += self.observe(on: ImmediateExecutionContext) { task in + compositeDisposable += self.observe(on: nil) { task in serialDisposable.otherDisposable?.dispose() - serialDisposable.otherDisposable = task.observe(on: ImmediateExecutionContext) { event in + serialDisposable.otherDisposable = task.observe(on: nil) { event in switch event { case .Failure(let error): @@ -85,7 +85,7 @@ public extension StreamType where Event: OperationType { let task = taskQueue.removeAtIndex(0) serialDisposable.otherDisposable?.dispose() - serialDisposable.otherDisposable = task.observe(on: ImmediateExecutionContext) { event in + serialDisposable.otherDisposable = task.observe(on: nil) { event in switch event { case .Failure(let error): observer.failure(error) @@ -107,7 +107,7 @@ public extension StreamType where Event: OperationType { } } - compositeDisposable += self.observe(on: ImmediateExecutionContext) { task in + compositeDisposable += self.observe(on: nil) { task in addToQueue(task) } diff --git a/ReactiveKit/Other/TokenizedCollection.swift b/ReactiveKit/Other/TokenizedCollection.swift deleted file mode 100644 index bce1703..0000000 --- a/ReactiveKit/Other/TokenizedCollection.swift +++ /dev/null @@ -1,54 +0,0 @@ -// -// The MIT License (MIT) -// -// Copyright (c) 2015 Srdan Rasic (@srdanrasic) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -public class TokenizedCollection { - public typealias Token = Int64 - - private var storage: [Token:T] = [:] - private var nextToken: Token = 0 - private let lock = RecursiveLock(name: "com.ReactiveKit.ReactiveKit.TokenizedCollection") - - public var count: Int { - return storage.count - } - - public init() {} - - public func insert(element: T) -> DisposableType { - lock.lock() - let token = nextToken - nextToken = nextToken + 1 - lock.unlock() - - storage[token] = element - - return BlockDisposable { [weak self] in - self?.storage.removeValueForKey(token) - } - } - - public func forEach(body: T -> ()) { - return storage.values.forEach(body) - } -} diff --git a/ReactiveKit/Streams/ActiveStream.swift b/ReactiveKit/Streams/ActiveStream.swift index 8fc00db..cc9b31f 100644 --- a/ReactiveKit/Streams/ActiveStream.swift +++ b/ReactiveKit/Streams/ActiveStream.swift @@ -22,18 +22,19 @@ // THE SOFTWARE. // -public protocol ActiveStreamType: StreamType { - var buffer: StreamBuffer { get } -} - -public class ActiveStream: ActiveStreamType { +public class ActiveStream: StreamType { public typealias Observer = Event -> () - - public var buffer: StreamBuffer - + private typealias Token = Int64 + + private var nextToken: Token = 0 + public var observers: ContiguousArray = [] + private var observerStorage: [Token: Observer] = [:] { + didSet { + observers = ContiguousArray(observerStorage.values) + } + } - private var observers = TokenizedCollection() private let lock = RecursiveLock(name: "com.ReactiveKit.ReactiveKit.ActiveStream") private var isDispatchInProgress: Bool = false @@ -41,9 +42,7 @@ public class ActiveStream: ActiveStreamType { private weak var selfReference: Reference>? = nil - public required init(limit: Int = 0, @noescape producer: Observer -> DisposableType?) { - self.buffer = StreamBuffer(limit: limit) - + public init(@noescape producer: Observer -> DisposableType?) { let tmpSelfReference = Reference(self) tmpSelfReference.release() @@ -58,21 +57,22 @@ public class ActiveStream: ActiveStreamType { self.selfReference = tmpSelfReference } - public init(limit: Int = 0) { - self.buffer = StreamBuffer(limit: limit) + public init() { let tmpSelfReference = Reference(self) tmpSelfReference.release() self.selfReference = tmpSelfReference } - public func observe(on context: ExecutionContext = ImmediateOnMainExecutionContext, observer: Observer) -> DisposableType { + public func observe(on context: ExecutionContext? = ImmediateOnMainExecutionContext, observer: Observer) -> DisposableType { selfReference?.retain() - - let observer = { e in context { observer(e) } } - - let disposable = registerObserver(observer) - buffer.replay(observer) - + + var contextedObserver = observer + if let context = context { + contextedObserver = { e in context { observer(e) } } + } + + let disposable = registerObserver(contextedObserver) + let cleanupDisposable = BlockDisposable { [weak self] in disposable.dispose() @@ -87,34 +87,33 @@ public class ActiveStream: ActiveStreamType { return cleanupDisposable } - - public func lastEvent() throws -> Event { - return try buffer.last() - } - public func next(event: Event) { - buffer.next(event) - dispatchNext(event) - } - - internal func registerDisposable(disposable: DisposableType) { - deinitDisposable.addDisposable(disposable) - } - - private func dispatchNext(event: Event) { guard !isDispatchInProgress else { return } lock.lock() isDispatchInProgress = true - observers.forEach { send in - send(event) + for observer in observers { + observer(event) } isDispatchInProgress = false lock.unlock() } - + + internal func registerDisposable(disposable: DisposableType) { + deinitDisposable.addDisposable(disposable) + } + private func registerObserver(observer: Observer) -> DisposableType { - return observers.insert(observer) + lock.lock() + let token = nextToken + nextToken = nextToken + 1 + lock.unlock() + + observerStorage[token] = observer + + return BlockDisposable { [weak self] in + self?.observerStorage.removeValueForKey(token) + } } deinit { @@ -123,8 +122,6 @@ public class ActiveStream: ActiveStreamType { } @warn_unused_result -public func create(limit: Int = Int.max, producer: (Event -> ()) -> DisposableType?) -> ActiveStream { - return ActiveStream(limit: limit, producer: producer) +public func create(producer: (Event -> ()) -> DisposableType?) -> ActiveStream { + return ActiveStream(producer: producer) } - - diff --git a/ReactiveKit/Streams/Stream.swift b/ReactiveKit/Streams/Stream.swift index 13f22e6..092c8a1 100644 --- a/ReactiveKit/Streams/Stream.swift +++ b/ReactiveKit/Streams/Stream.swift @@ -32,11 +32,19 @@ public struct Stream: StreamType { self.producer = producer } - public func observe(on context: ExecutionContext, observer: Observer) -> DisposableType { + public func observe(on context: ExecutionContext? = ImmediateOnMainExecutionContext, observer: Observer) -> DisposableType { let serialDisposable = SerialDisposable(otherDisposable: nil) - serialDisposable.otherDisposable = producer { event in - if !serialDisposable.isDisposed { - context { + if let context = context { + serialDisposable.otherDisposable = producer { event in + if !serialDisposable.isDisposed { + context { + observer(event) + } + } + } + } else { + serialDisposable.otherDisposable = producer { event in + if !serialDisposable.isDisposed { observer(event) } } diff --git a/ReactiveKit/Streams/StreamType.swift b/ReactiveKit/Streams/StreamType.swift index 41c2807..6809d29 100644 --- a/ReactiveKit/Streams/StreamType.swift +++ b/ReactiveKit/Streams/StreamType.swift @@ -26,14 +26,14 @@ import Foundation public protocol StreamType { typealias Event - func observe(on context: ExecutionContext, observer: Event -> ()) -> DisposableType + func observe(on context: ExecutionContext?, observer: Event -> ()) -> DisposableType } extension StreamType { @warn_unused_result - public func share(limit: Int = Int.max, context: ExecutionContext = Queue.main.context) -> ActiveStream { - return create(limit) { observer in + public func share(limit: Int = Int.max, context: ExecutionContext? = ImmediateOnMainExecutionContext) -> ObservableBuffer { + return ObservableBuffer(limit: limit) { observer in return self.observe(on: context, observer: observer) } } @@ -44,7 +44,7 @@ extension StreamType { @warn_unused_result public func map(transform: Event -> U) -> Stream { return create { observer in - return self.observe(on: ImmediateExecutionContext) { event in + return self.observe(on: nil) { event in observer(transform(event)) } } @@ -53,14 +53,14 @@ extension StreamType { @warn_unused_result public func filter(include: Event -> Bool) -> Stream { return create { observer in - return self.observe(on: ImmediateExecutionContext) { event in + return self.observe(on: nil) { event in if include(event) { observer(event) } } } } - + @warn_unused_result public func switchTo(context: ExecutionContext) -> Stream { return create { observer in @@ -72,7 +72,7 @@ extension StreamType { public func zipPrevious() -> Stream<(Event?, Event)> { return create { observer in var previous: Event? = nil - return self.observe(on: ImmediateExecutionContext) { event in + return self.observe(on: nil) { event in observer(previous, event) previous = event } @@ -102,7 +102,7 @@ extension StreamType { let blockDisposable = BlockDisposable { tryDispatch = nil } let compositeDisposable = CompositeDisposable([blockDisposable]) - compositeDisposable += self.observe(on: ImmediateExecutionContext) { event in + compositeDisposable += self.observe(on: nil) { event in latestEvent = event latestEventDate = NSDate() @@ -120,7 +120,7 @@ extension StreamType { var shouldDispatch: Bool = true var latestEvent: Event! = nil - return self.observe(on: ImmediateExecutionContext) { event in + return self.observe(on: nil) { event in latestEvent = event guard shouldDispatch == true else { return } @@ -139,7 +139,7 @@ extension StreamType { @warn_unused_result public func skip(var count: Int) -> Stream { return create { observer in - return self.observe(on: ImmediateExecutionContext) { event in + return self.observe(on: nil) { event in if count > 0 { count-- } else { @@ -153,7 +153,7 @@ extension StreamType { public func startWith(event: Event) -> Stream { return create { observer in observer(event) - return self.observe(on: ImmediateExecutionContext) { event in + return self.observe(on: nil) { event in observer(event) } } @@ -173,14 +173,14 @@ extension StreamType { } } - let selfDisposable = self.observe(on: ImmediateExecutionContext) { event in + let selfDisposable = self.observe(on: nil) { event in queue.sync { selfEvent = event dispatchIfPossible() } } - let otherDisposable = other.observe(on: ImmediateExecutionContext) { event in + let otherDisposable = other.observe(on: nil) { event in queue.sync { otherEvent = event dispatchIfPossible() @@ -207,14 +207,14 @@ extension StreamType { } } - let selfDisposable = self.observe(on: ImmediateExecutionContext) { event in + let selfDisposable = self.observe(on: nil) { event in queue.sync { selfBuffer.append(event) dispatchIfPossible() } } - let otherDisposable = other.observe(on: ImmediateExecutionContext) { event in + let otherDisposable = other.observe(on: nil) { event in queue.sync { otherBuffer.append(event) dispatchIfPossible() @@ -231,7 +231,7 @@ extension StreamType where Event: OptionalType { @warn_unused_result public func ignoreNil() -> Stream { return create { observer in - return self.observe(on: ImmediateExecutionContext) { event in + return self.observe(on: nil) { event in if let event = event._unbox { observer(event) } @@ -246,7 +246,7 @@ extension StreamType where Event: Equatable { public func distinct() -> Stream { return create { observer in var lastEvent: Event? = nil - return self.observe(on: ImmediateExecutionContext) { event in + return self.observe(on: nil) { event in if lastEvent == nil || lastEvent! != event { observer(event) lastEvent = event @@ -262,7 +262,7 @@ public extension StreamType where Event: OptionalType, Event.Wrapped: Equatable public func distinctOptional() -> Stream { return create { observer in var lastEvent: Event.Wrapped? = nil - return self.observe(on: ImmediateExecutionContext) { event in + return self.observe(on: nil) { event in switch (lastEvent, event._unbox) { case (.None, .Some(let new)): @@ -287,8 +287,8 @@ public extension StreamType where Event: StreamType { public func merge() -> Stream { return create { observer in let compositeDisposable = CompositeDisposable() - compositeDisposable += self.observe(on: ImmediateExecutionContext) { innerObserver in - compositeDisposable += innerObserver.observe(on: ImmediateExecutionContext, observer: observer) + compositeDisposable += self.observe(on: nil) { innerObserver in + compositeDisposable += innerObserver.observe(on: nil, observer: observer) } return compositeDisposable } @@ -300,9 +300,9 @@ public extension StreamType where Event: StreamType { let serialDisposable = SerialDisposable(otherDisposable: nil) let compositeDisposable = CompositeDisposable([serialDisposable]) - compositeDisposable += self.observe(on: ImmediateExecutionContext) { innerObserver in + compositeDisposable += self.observe(on: nil) { innerObserver in serialDisposable.otherDisposable?.dispose() - serialDisposable.otherDisposable = innerObserver.observe(on: ImmediateExecutionContext, observer: observer) + serialDisposable.otherDisposable = innerObserver.observe(on: nil, observer: observer) } return compositeDisposable diff --git a/ReactiveKitTests/OperationSpec.swift b/ReactiveKitTests/OperationSpec.swift index 1427553..64bc0e4 100644 --- a/ReactiveKitTests/OperationSpec.swift +++ b/ReactiveKitTests/OperationSpec.swift @@ -155,9 +155,9 @@ class OperationSpec: QuickSpec { innerDisposable1 = SimpleDisposable() innerDisposable2 = SimpleDisposable() - outerProducer = ActiveStream>(limit: 0, producer: { s in outerDisposable }) - innerProducer1 = ActiveStream>(limit: 0, producer: { s in innerDisposable1 }) - innerProducer2 = ActiveStream>(limit: 0, producer: { s in innerDisposable2 }) + outerProducer = ActiveStream>(producer: { s in outerDisposable }) + innerProducer1 = ActiveStream>(producer: { s in innerDisposable1 }) + innerProducer2 = ActiveStream>(producer: { s in innerDisposable2 }) operation = create { observer in outerProducer.observe(on: ImmediateExecutionContext) { e in @@ -324,9 +324,9 @@ class OperationSpec: QuickSpec { innerDisposable1 = SimpleDisposable() innerDisposable2 = SimpleDisposable() - outerProducer = ActiveStream>(limit: 0, producer: { s in outerDisposable }) - innerProducer1 = ActiveStream>(limit: 0, producer: { s in innerDisposable1 }) - innerProducer2 = ActiveStream>(limit: 0, producer: { s in innerDisposable2 }) + outerProducer = ActiveStream>(producer: { s in outerDisposable }) + innerProducer1 = ActiveStream>(producer: { s in innerDisposable1 }) + innerProducer2 = ActiveStream>(producer: { s in innerDisposable2 }) operation = create { observer in outerProducer.observe(on: ImmediateExecutionContext) { e in @@ -474,9 +474,9 @@ class OperationSpec: QuickSpec { var innerDisposable1: SimpleDisposable! var innerDisposable2: SimpleDisposable! - var outerProducer: ActiveStream>! - var innerProducer1: ActiveStream>! - var innerProducer2: ActiveStream>! + var outerProducer: ObservableBuffer>! + var innerProducer1: ObservableBuffer>! + var innerProducer2: ObservableBuffer>! var operation: Operation! @@ -494,9 +494,9 @@ class OperationSpec: QuickSpec { innerDisposable1 = SimpleDisposable() innerDisposable2 = SimpleDisposable() - outerProducer = ActiveStream>(limit: 10, producer: { s in outerDisposable }) - innerProducer1 = ActiveStream>(limit: 10, producer: { s in innerDisposable1 }) - innerProducer2 = ActiveStream>(limit: 10, producer: { s in innerDisposable2 }) + outerProducer = ObservableBuffer>(limit: 10, producer: { s in outerDisposable }) + innerProducer1 = ObservableBuffer>(limit: 10, producer: { s in innerDisposable1 }) + innerProducer2 = ObservableBuffer>(limit: 10, producer: { s in innerDisposable2 }) operation = create { observer in outerProducer.observe(on: ImmediateExecutionContext) { e in diff --git a/ReactiveKitTests/PerformanceTests.swift b/ReactiveKitTests/PerformanceTests.swift new file mode 100644 index 0000000..8be50fa --- /dev/null +++ b/ReactiveKitTests/PerformanceTests.swift @@ -0,0 +1,56 @@ +// +// PerformanceTests.swift +// ReactiveKit +// +// Created by Srdan Rasic on 23/11/15. +// Copyright © 2015 Srdan Rasic. All rights reserved. +// + +import XCTest +@testable import ReactiveKit + +class PerformanceTests: XCTestCase { + + func test1() { + measureBlock { + var counter: Int = 0 + let observable = Observable(0) + + observable.observe(on: nil) { counter += $0 } + + for i in 1..<10000 { + observable.value = i + } + } + } + + func test2() { + measureBlock { + var counter: Int = 0 + let observable = Observable(0) + + for _ in 1..<30 { + observable.observe(on: nil) { counter += $0 } + } + + for i in 1..<10000 { + observable.value = i + } + } + } + + func test_measure_3() { + measureBlock { + let observable = Observable(0) + var counter : Int = 0 + + for _ in 1..<30 { + observable.filter{ $0 % 2 == 0 }.observe(on: nil) { counter += $0 } + } + + for i in 1..<10000 { + observable.value = i + } + } + } +}