Unit test pass and all of the bugs are fixed.
This commit is contained in:
parent
7a5bb82ce4
commit
f9d9c12a5c
|
|
@ -0,0 +1,540 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
C809A1361AD009FB001AA8FE /* CollectionViewImageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C809A1351AD009FB001AA8FE /* CollectionViewImageCell.swift */; };
|
||||
C81175AB1ACEEBAA001521F4 /* Wireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = C81175AA1ACEEBAA001521F4 /* Wireframe.swift */; };
|
||||
C81553B21A98A94700C63152 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C81553B11A98A94700C63152 /* AppDelegate.swift */; };
|
||||
C81553B51A98A94700C63152 /* Example.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = C81553B31A98A94700C63152 /* Example.xcdatamodeld */; };
|
||||
C81553BC1A98A94700C63152 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C81553BB1A98A94700C63152 /* Images.xcassets */; };
|
||||
C81553CB1A98A94700C63152 /* ExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C81553CA1A98A94700C63152 /* ExampleTests.swift */; };
|
||||
C8AD4A741AD0253200C12FBF /* Rx.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C81553FA1A98AB7800C63152 /* Rx.framework */; };
|
||||
C8AD4A751AD0253300C12FBF /* Rx.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C81553FA1A98AB7800C63152 /* Rx.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
C8AD4A771AD0253600C12FBF /* RxCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C8AD4A761AD0253600C12FBF /* RxCocoa.framework */; };
|
||||
C8AD4A781AD0253600C12FBF /* RxCocoa.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C8AD4A761AD0253600C12FBF /* RxCocoa.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
C8D7B92D1ACFEAC900342508 /* SearchResultViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8D7B9271ACFEAC900342508 /* SearchResultViewModel.swift */; };
|
||||
C8D7B92E1ACFEAC900342508 /* SearchViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8D7B9281ACFEAC900342508 /* SearchViewModel.swift */; };
|
||||
C8D7B9341ACFEAEA00342508 /* WikipediaSearchCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8D7B9301ACFEAEA00342508 /* WikipediaSearchCell.swift */; };
|
||||
C8D7B9351ACFEAEA00342508 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = C8D7B9311ACFEAEA00342508 /* LaunchScreen.xib */; };
|
||||
C8D7B9361ACFEAEA00342508 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C8D7B9321ACFEAEA00342508 /* Main.storyboard */; };
|
||||
C8D7B9371ACFEAEA00342508 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8D7B9331ACFEAEA00342508 /* ViewController.swift */; };
|
||||
C8DDCFD31AC6F17500414017 /* HtmlParsing.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8DDCFD21AC6F17500414017 /* HtmlParsing.swift */; };
|
||||
C8DDCFD41AC6F46200414017 /* HtmlParsing.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8DDCFD21AC6F17500414017 /* HtmlParsing.swift */; };
|
||||
C8DDCFE41AC7400C00414017 /* Example.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8DDCFE31AC7400C00414017 /* Example.swift */; };
|
||||
C8DDCFE61AC757AE00414017 /* ImageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8DDCFE51AC757AE00414017 /* ImageService.swift */; };
|
||||
C8DDCFEB1AC757E700414017 /* WikipediaAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8DDCFE81AC757E700414017 /* WikipediaAPI.swift */; };
|
||||
C8DDCFEC1AC757E700414017 /* WikipediaPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8DDCFE91AC757E700414017 /* WikipediaPage.swift */; };
|
||||
C8DDCFED1AC757E700414017 /* WikipediaSearchResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8DDCFEA1AC757E700414017 /* WikipediaSearchResult.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
C81553C51A98A94700C63152 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = C81553A41A98A94700C63152 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = C81553AB1A98A94700C63152;
|
||||
remoteInfo = Example;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
C8AD4A6F1AD016DB00C12FBF /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
C8AD4A781AD0253600C12FBF /* RxCocoa.framework in Embed Frameworks */,
|
||||
C8AD4A751AD0253300C12FBF /* Rx.framework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
C809A1351AD009FB001AA8FE /* CollectionViewImageCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionViewImageCell.swift; sourceTree = "<group>"; };
|
||||
C81175AA1ACEEBAA001521F4 /* Wireframe.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Wireframe.swift; sourceTree = "<group>"; };
|
||||
C81553AC1A98A94700C63152 /* RxExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RxExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C81553B01A98A94700C63152 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
C81553B11A98A94700C63152 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
C81553B41A98A94700C63152 /* Example.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Example.xcdatamodel; sourceTree = "<group>"; };
|
||||
C81553BB1A98A94700C63152 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
|
||||
C81553C41A98A94700C63152 /* ExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C81553C91A98A94700C63152 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
C81553CA1A98A94700C63152 /* ExampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExampleTests.swift; sourceTree = "<group>"; };
|
||||
C81553FA1A98AB7800C63152 /* Rx.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Rx.framework; path = "../../../Library/Developer/Xcode/DerivedData/Rx-cfkyozdvlaegqibzixjokeysigeo/Build/Products/Debug-iphoneos/Rx.framework"; sourceTree = "<group>"; };
|
||||
C8AD4A761AD0253600C12FBF /* RxCocoa.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; name = RxCocoa.framework; path = "/Users/kzaher/Library/Developer/Xcode/DerivedData/Rx-cfkyozdvlaegqibzixjokeysigeo/Build/Products/Debug-iphoneos/RxCocoa.framework"; sourceTree = "<absolute>"; };
|
||||
C8D7B9271ACFEAC900342508 /* SearchResultViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchResultViewModel.swift; sourceTree = "<group>"; };
|
||||
C8D7B9281ACFEAC900342508 /* SearchViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchViewModel.swift; sourceTree = "<group>"; };
|
||||
C8D7B9301ACFEAEA00342508 /* WikipediaSearchCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WikipediaSearchCell.swift; sourceTree = "<group>"; };
|
||||
C8D7B9311ACFEAEA00342508 /* LaunchScreen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LaunchScreen.xib; sourceTree = "<group>"; };
|
||||
C8D7B9321ACFEAEA00342508 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = "<group>"; };
|
||||
C8D7B9331ACFEAEA00342508 /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
||||
C8DDCFD21AC6F17500414017 /* HtmlParsing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HtmlParsing.swift; sourceTree = "<group>"; };
|
||||
C8DDCFE31AC7400C00414017 /* Example.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Example.swift; sourceTree = "<group>"; };
|
||||
C8DDCFE51AC757AE00414017 /* ImageService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageService.swift; sourceTree = "<group>"; };
|
||||
C8DDCFE81AC757E700414017 /* WikipediaAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WikipediaAPI.swift; sourceTree = "<group>"; };
|
||||
C8DDCFE91AC757E700414017 /* WikipediaPage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WikipediaPage.swift; sourceTree = "<group>"; };
|
||||
C8DDCFEA1AC757E700414017 /* WikipediaSearchResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WikipediaSearchResult.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
C81553A91A98A94700C63152 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C8AD4A771AD0253600C12FBF /* RxCocoa.framework in Frameworks */,
|
||||
C8AD4A741AD0253200C12FBF /* Rx.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
C81553C11A98A94700C63152 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
C81553A31A98A94700C63152 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C8AD4A761AD0253600C12FBF /* RxCocoa.framework */,
|
||||
C81553AE1A98A94700C63152 /* Example */,
|
||||
C81553C71A98A94700C63152 /* ExampleTests */,
|
||||
C81553AD1A98A94700C63152 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C81553AD1A98A94700C63152 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C81553AC1A98A94700C63152 /* RxExample.app */,
|
||||
C81553C41A98A94700C63152 /* ExampleTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C81553AE1A98A94700C63152 /* Example */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C8D7B92F1ACFEAEA00342508 /* Interface */,
|
||||
C8D7B9261ACFEAC900342508 /* ViewModels */,
|
||||
C81C49E31AC4114E001D7A5E /* Services */,
|
||||
C81553B11A98A94700C63152 /* AppDelegate.swift */,
|
||||
C81553BB1A98A94700C63152 /* Images.xcassets */,
|
||||
C81553B31A98A94700C63152 /* Example.xcdatamodeld */,
|
||||
C81553AF1A98A94700C63152 /* Supporting Files */,
|
||||
C8DDCFE31AC7400C00414017 /* Example.swift */,
|
||||
C81175AA1ACEEBAA001521F4 /* Wireframe.swift */,
|
||||
);
|
||||
path = Example;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C81553AF1A98A94700C63152 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C81553B01A98A94700C63152 /* Info.plist */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C81553C71A98A94700C63152 /* ExampleTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C81553CA1A98A94700C63152 /* ExampleTests.swift */,
|
||||
C81553C81A98A94700C63152 /* Supporting Files */,
|
||||
);
|
||||
path = ExampleTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C81553C81A98A94700C63152 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C81553C91A98A94700C63152 /* Info.plist */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C81C49E31AC4114E001D7A5E /* Services */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C8DDCFE71AC757E700414017 /* WikipediaAPI */,
|
||||
C8DDCFD21AC6F17500414017 /* HtmlParsing.swift */,
|
||||
C8DDCFE51AC757AE00414017 /* ImageService.swift */,
|
||||
);
|
||||
path = Services;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C8D7B9261ACFEAC900342508 /* ViewModels */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C8D7B9271ACFEAC900342508 /* SearchResultViewModel.swift */,
|
||||
C8D7B9281ACFEAC900342508 /* SearchViewModel.swift */,
|
||||
);
|
||||
path = ViewModels;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C8D7B92F1ACFEAEA00342508 /* Interface */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C8D7B9301ACFEAEA00342508 /* WikipediaSearchCell.swift */,
|
||||
C809A1351AD009FB001AA8FE /* CollectionViewImageCell.swift */,
|
||||
C8D7B9311ACFEAEA00342508 /* LaunchScreen.xib */,
|
||||
C8D7B9321ACFEAEA00342508 /* Main.storyboard */,
|
||||
C8D7B9331ACFEAEA00342508 /* ViewController.swift */,
|
||||
);
|
||||
path = Interface;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C8DDCFE71AC757E700414017 /* WikipediaAPI */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C8DDCFE81AC757E700414017 /* WikipediaAPI.swift */,
|
||||
C8DDCFE91AC757E700414017 /* WikipediaPage.swift */,
|
||||
C8DDCFEA1AC757E700414017 /* WikipediaSearchResult.swift */,
|
||||
);
|
||||
path = WikipediaAPI;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
C81553AB1A98A94700C63152 /* RxExample */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = C81553CE1A98A94700C63152 /* Build configuration list for PBXNativeTarget "RxExample" */;
|
||||
buildPhases = (
|
||||
C81553A81A98A94700C63152 /* Sources */,
|
||||
C81553A91A98A94700C63152 /* Frameworks */,
|
||||
C81553AA1A98A94700C63152 /* Resources */,
|
||||
C8AD4A6F1AD016DB00C12FBF /* Embed Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = RxExample;
|
||||
productName = Example;
|
||||
productReference = C81553AC1A98A94700C63152 /* RxExample.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
C81553C31A98A94700C63152 /* ExampleTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = C81553D11A98A94700C63152 /* Build configuration list for PBXNativeTarget "ExampleTests" */;
|
||||
buildPhases = (
|
||||
C81553C01A98A94700C63152 /* Sources */,
|
||||
C81553C11A98A94700C63152 /* Frameworks */,
|
||||
C81553C21A98A94700C63152 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
C81553C61A98A94700C63152 /* PBXTargetDependency */,
|
||||
);
|
||||
name = ExampleTests;
|
||||
productName = ExampleTests;
|
||||
productReference = C81553C41A98A94700C63152 /* ExampleTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
C81553A41A98A94700C63152 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0610;
|
||||
ORGANIZATIONNAME = "Krunoslav Zaher";
|
||||
TargetAttributes = {
|
||||
C81553AB1A98A94700C63152 = {
|
||||
CreatedOnToolsVersion = 6.1.1;
|
||||
};
|
||||
C81553C31A98A94700C63152 = {
|
||||
CreatedOnToolsVersion = 6.1.1;
|
||||
TestTargetID = C81553AB1A98A94700C63152;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = C81553A71A98A94700C63152 /* Build configuration list for PBXProject "Example" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = C81553A31A98A94700C63152;
|
||||
productRefGroup = C81553AD1A98A94700C63152 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
C81553AB1A98A94700C63152 /* RxExample */,
|
||||
C81553C31A98A94700C63152 /* ExampleTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
C81553AA1A98A94700C63152 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C8D7B9361ACFEAEA00342508 /* Main.storyboard in Resources */,
|
||||
C8D7B9351ACFEAEA00342508 /* LaunchScreen.xib in Resources */,
|
||||
C81553BC1A98A94700C63152 /* Images.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
C81553C21A98A94700C63152 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
C81553A81A98A94700C63152 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C8DDCFEC1AC757E700414017 /* WikipediaPage.swift in Sources */,
|
||||
C8D7B9341ACFEAEA00342508 /* WikipediaSearchCell.swift in Sources */,
|
||||
C809A1361AD009FB001AA8FE /* CollectionViewImageCell.swift in Sources */,
|
||||
C8DDCFEB1AC757E700414017 /* WikipediaAPI.swift in Sources */,
|
||||
C8DDCFED1AC757E700414017 /* WikipediaSearchResult.swift in Sources */,
|
||||
C8DDCFE41AC7400C00414017 /* Example.swift in Sources */,
|
||||
C8D7B92E1ACFEAC900342508 /* SearchViewModel.swift in Sources */,
|
||||
C81553B51A98A94700C63152 /* Example.xcdatamodeld in Sources */,
|
||||
C81175AB1ACEEBAA001521F4 /* Wireframe.swift in Sources */,
|
||||
C8D7B9371ACFEAEA00342508 /* ViewController.swift in Sources */,
|
||||
C8D7B92D1ACFEAC900342508 /* SearchResultViewModel.swift in Sources */,
|
||||
C8DDCFD31AC6F17500414017 /* HtmlParsing.swift in Sources */,
|
||||
C8DDCFE61AC757AE00414017 /* ImageService.swift in Sources */,
|
||||
C81553B21A98A94700C63152 /* AppDelegate.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
C81553C01A98A94700C63152 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C81553CB1A98A94700C63152 /* ExampleTests.swift in Sources */,
|
||||
C8DDCFD41AC6F46200414017 /* HtmlParsing.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
C81553C61A98A94700C63152 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = C81553AB1A98A94700C63152 /* RxExample */;
|
||||
targetProxy = C81553C51A98A94700C63152 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
C81553CC1A98A94700C63152 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
C81553CD1A98A94700C63152 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
C81553CF1A98A94700C63152 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer: Krunoslav Zaher (KQ9K2C6LEP)";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"/Users/kzaher/Projects/Rx/Rx/build/Debug-iphoneos",
|
||||
"$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/Rx-cfkyozdvlaegqibzixjokeysigeo/Build/Products/Debug-iphoneos",
|
||||
);
|
||||
INFOPLIST_FILE = Example/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
OTHER_SWIFT_FLAGS = "-D DEBUG";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE = "7db5c878-b123-4595-ac8d-4b3c3937d3ec";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
C81553D01A98A94700C63152 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer: Krunoslav Zaher (KQ9K2C6LEP)";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"/Users/kzaher/Projects/Rx/Rx/build/Debug-iphoneos",
|
||||
"$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/Rx-cfkyozdvlaegqibzixjokeysigeo/Build/Products/Debug-iphoneos",
|
||||
);
|
||||
INFOPLIST_FILE = Example/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE = "7db5c878-b123-4595-ac8d-4b3c3937d3ec";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
C81553D21A98A94700C63152 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = ExampleTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
C81553D31A98A94700C63152 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = ExampleTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
C81553A71A98A94700C63152 /* Build configuration list for PBXProject "Example" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
C81553CC1A98A94700C63152 /* Debug */,
|
||||
C81553CD1A98A94700C63152 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
C81553CE1A98A94700C63152 /* Build configuration list for PBXNativeTarget "RxExample" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
C81553CF1A98A94700C63152 /* Debug */,
|
||||
C81553D01A98A94700C63152 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
C81553D11A98A94700C63152 /* Build configuration list for PBXNativeTarget "ExampleTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
C81553D21A98A94700C63152 /* Debug */,
|
||||
C81553D31A98A94700C63152 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCVersionGroup section */
|
||||
C81553B31A98A94700C63152 /* Example.xcdatamodeld */ = {
|
||||
isa = XCVersionGroup;
|
||||
children = (
|
||||
C81553B41A98A94700C63152 /* Example.xcdatamodel */,
|
||||
);
|
||||
currentVersion = C81553B41A98A94700C63152 /* Example.xcdatamodel */;
|
||||
path = Example.xcdatamodeld;
|
||||
sourceTree = "<group>";
|
||||
versionGroupType = wrapper.xcdatamodel;
|
||||
};
|
||||
/* End XCVersionGroup section */
|
||||
};
|
||||
rootObject = C81553A41A98A94700C63152 /* Project object */;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:Example.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0610"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C81553AB1A98A94700C63152"
|
||||
BuildableName = "RxExample.app"
|
||||
BlueprintName = "RxExample"
|
||||
ReferencedContainer = "container:Example.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C81553C31A98A94700C63152"
|
||||
BuildableName = "ExampleTests.xctest"
|
||||
BlueprintName = "ExampleTests"
|
||||
ReferencedContainer = "container:Example.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
buildConfiguration = "Debug">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C81553C31A98A94700C63152"
|
||||
BuildableName = "ExampleTests.xctest"
|
||||
BlueprintName = "ExampleTests"
|
||||
ReferencedContainer = "container:Example.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C81553AB1A98A94700C63152"
|
||||
BuildableName = "RxExample.app"
|
||||
BlueprintName = "RxExample"
|
||||
ReferencedContainer = "container:Example.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Debug"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C81553AB1A98A94700C63152"
|
||||
BuildableName = "RxExample.app"
|
||||
BlueprintName = "RxExample"
|
||||
ReferencedContainer = "container:Example.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Release"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C81553AB1A98A94700C63152"
|
||||
BuildableName = "RxExample.app"
|
||||
BlueprintName = "RxExample"
|
||||
ReferencedContainer = "container:Example.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>Example.xcscheme</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>SuppressBuildableAutocreation</key>
|
||||
<dict>
|
||||
<key>C81553AB1A98A94700C63152</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>C81553C31A98A94700C63152</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>_XCCurrentVersionName</key>
|
||||
<string>Example.xcdatamodel</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model name="Test1.xcdatamodel" userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="1" systemVersion="11A491" minimumToolsVersion="Automatic" macOSVersion="Automatic" iOSVersion="Automatic">
|
||||
<elements/>
|
||||
</model>
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>Krunoslav-Zaher.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,9 @@
|
|||
**The MIT License**
|
||||
**Copyright (c) 2015 Krunoslav Zaher**
|
||||
**All rights reserved.**
|
||||
|
||||
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.
|
||||
|
|
@ -0,0 +1,267 @@
|
|||
RxSwift (0.7): Reactive extensions for Swift
|
||||
======================================
|
||||
|
||||
Xcode 6.3 / Swift 1.2 required
|
||||
|
||||
This is a Swift port of Reactive extensions.
|
||||
|
||||
[https://github.com/Reactive-Extensions](https://github.com/Reactive-Extensions)
|
||||
|
||||
Like the original Rx, it's intention is to enable easy composition of asynchronous operations and event streams.
|
||||
|
||||
It tries to port as many concepts from the original Rx as possible, but some concepts were adapted for more pleasant and performant integration with iOS/OSX environment.
|
||||
|
||||
Probably the best analogy for those who have never heard of Rx would be:
|
||||
|
||||
|
||||
```
|
||||
git diff | grep bug | less # linux pipes - programs communicate by sending
|
||||
# sequences of bytes, words, lines, '\0' terminated strings...
|
||||
```
|
||||
would become if written in RxSwift
|
||||
```
|
||||
gitDiff() >- grep("bug") >- less // rx sink (>-) operator - rx units communicate by sending
|
||||
// sequences of swift objects
|
||||
```
|
||||
|
||||
Rx is implemented as a slightly modified version of observer pattern.
|
||||
|
||||
[http://en.wikipedia.org/wiki/Observer_pattern](http://en.wikipedia.org/wiki/Observer_pattern)
|
||||
|
||||
It probably sounds little weird at first, but those abstractions are equivalent. Following paragraphs explain that in more detail.
|
||||
|
||||
## But first, why would somebody want to use Rx?
|
||||
|
||||
Writing correct asynchronous programs is hard because every line of code has to deal with following concerns:
|
||||
|
||||
* Resource management (disposal of memory allocations, sockets, file handles)
|
||||
* Asynchronous operations (composition, cancellation, deadlocks)
|
||||
* Error handling
|
||||
|
||||
Thinking about those concerns over and over again is tedious and error prone experience. Rx provides a level of abstraction that hides all of that complexity and makes writing performant and correct programs easy.
|
||||
|
||||
It provides default implementations of most common units/operations of async programs and enables easy bridging of existing imperative APIs in a couple of lines of code.
|
||||
|
||||
In the context of Rx, data is modeled as "lazy evaluated" sequence of swift objects. That includes:
|
||||
|
||||
* Asynchronous operations
|
||||
* UI actions
|
||||
* Observing of property changes
|
||||
* ...
|
||||
|
||||
It is also pretty straightforward to create custom sequence transformers.
|
||||
|
||||
## What's so special about sequences?
|
||||
|
||||
Everybody is familiar with sequences. Lists/sequences are probably one of the first concepts programmers learn.
|
||||
They are easy to visualize and easy to reason about.
|
||||
|
||||
Here is a sequence of numbers
|
||||
|
||||
|
||||
```
|
||||
--1--2--3--4--5--6--| // it terminates normally
|
||||
```
|
||||
|
||||
Here is another one with characters
|
||||
|
||||
```
|
||||
--a--b--a--a--a---d---X // it terminates with error
|
||||
```
|
||||
|
||||
Some sequences are finite, and some are infinite, like sequence of button taps
|
||||
|
||||
```
|
||||
---tap-tap-------tap--->
|
||||
```
|
||||
|
||||
These diagrams are called marble diagrams.
|
||||
|
||||
[http://rxmarbles.com/](http://rxmarbles.com/)
|
||||
|
||||
## How do sequences solve anything?
|
||||
|
||||
If everything is a sequence, and every operation is just a transformation of input sequence into output sequence then it's pretty straightforward to compose operations.
|
||||
|
||||
Asynchronous or time delayed operations don't cause any problems because elements of Rx sequences are accessed by registering observers and are not enumerated immediatelly. This can be viewed as a "lazy evaluation" implementation technique.
|
||||
|
||||
Resource management is also pretty natural. Sequence can release element computation resources once the observer has unsubscribed from receiving next elements. If no observer is waiting for next element to arrive, then it doesn't make sense to waste resources computing next elements. Of course, it's possible to implement other resource management logic.
|
||||
|
||||
## Example
|
||||
|
||||
This is Rx code taken from Rx example app inside repository. Example app transforms Wikipedia into a image search engine. It scrapes wikipedia pages for image URLs, and displayes all of the images in search results.
|
||||
|
||||
```swift
|
||||
results = searchText >- throttle(300, $.mainScheduler)
|
||||
>- distinctUntilChanged >- map { query in
|
||||
API.getSearchResults(query)
|
||||
}
|
||||
>- switchLatest >- map { results in
|
||||
convertResults(results)
|
||||
}
|
||||
```
|
||||
|
||||
On a conceptual level, this is the explanation of applied transformations:
|
||||
|
||||
* throttle - after new search value arrives, wait for 300 ms, if meanwhile new value is received, wait for another 300 ms
|
||||
* distinctUntilChanged - if received value is different then the last one, forward it, otherwise don't send anything
|
||||
* map - transforms sequence of search queries into a sequence of asynchronous URL requests
|
||||
* switchLatest - if a new search request arrives and old request hasn't finished, old request is cancelled and new search request starts
|
||||
* map - transforms a sequence of search results into view models suitable for user interface ingestion
|
||||
|
||||
That code alone won't actually start any request to server. It will only create a "template" of transformations that will be performed once somebody starts to observe results of that expression.
|
||||
|
||||
To start search requests, somebody needs to call something equivalent to.
|
||||
|
||||
```
|
||||
// starts listening for search results
|
||||
subscription = results >- subscribeNext { results in
|
||||
println("Here are search results \(results)")
|
||||
}
|
||||
sleep(10)
|
||||
// stops listening for search results
|
||||
subscription.dispose()
|
||||
```
|
||||
|
||||
So ...
|
||||
|
||||
## How does that work?
|
||||
|
||||
`throttle`, `distinctUntilChanged`, `switchLatest` ... are just normal functions that take `Observable<InputElement>` as input and return `Observable<OutputElement>` as output. `>-` is a sink operator that feeds `lhs` value to `rhs` function.
|
||||
|
||||
```
|
||||
func >- <In, Out>(source: In, transform: In -> Out) -> Out {
|
||||
return transform(source)
|
||||
}
|
||||
```
|
||||
This is actually a general purpose operator and it can be used outside the concept of `Observable<Element>` and sequences.
|
||||
|
||||
Sequences usually don't actually exist in memory. It is just an abstraction. Sequences of elements of type `Element` are represented by a corresponding `Observable<Element>`. Every time some element is observed it implicitly becomes next element in observed sequence of values. Even though the sequence of elements is implicit, that doesn't make it any less usefull.
|
||||
|
||||
```
|
||||
class Observable<Element> {
|
||||
func subscribe(observer: Observer<Element>) -> Disposable
|
||||
}
|
||||
```
|
||||
|
||||
To observe elements of a sequence `Observer<Element>` needs to subscribe to `Observable<Element>`. Every time next element of a sequence is produced, sequence terminates or fails with error, `Observable<Element>` with fire a notification to `Observer<Element>`.
|
||||
|
||||
```
|
||||
enum Event<Element> {
|
||||
case Next(Element) // next element of a sequence
|
||||
case Error(ErrorType) // sequence failed with error
|
||||
case Completed // sequence terminated successfully
|
||||
}
|
||||
|
||||
protocol ObserverType {
|
||||
func on(event: Event<Element>)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
When `Observer<Element>` wants to unsubscribe notifications from `Observable<Element>` it needs to call `dispose` on `Disposable` it received while subscribing.
|
||||
|
||||
```
|
||||
protocol Disposable
|
||||
{
|
||||
func dispose()
|
||||
}
|
||||
```
|
||||
|
||||
## Error handling
|
||||
|
||||
Error handling is pretty straightforward. If one sequence terminates with error, then all of the dependant sequences will terminate with error. It's usual short circuit logic.
|
||||
|
||||
Swift doesn't have a concept of exceptions so this project introduces `Result` enum.
|
||||
_(Haskell [`Either`](https://hackage.haskell.org/package/category-extras-0.52.0/docs/Control-Monad-Either.html) monad)_
|
||||
|
||||
```
|
||||
public enum Result<ResultType> {
|
||||
case Success(ResultType)
|
||||
case Error(ErrorType)
|
||||
}
|
||||
```
|
||||
|
||||
To enable writing more readable code, a few `Result` operators are introduced
|
||||
|
||||
```
|
||||
result1 >== { okValue in // success chaining operator
|
||||
// executed on success
|
||||
return ?
|
||||
} >>! { error in // error chaining operator
|
||||
// executed on error
|
||||
return ?
|
||||
}
|
||||
```
|
||||
|
||||
If some action needs to be peformed only after a successfull computation without using it's result then `>>>` is used.
|
||||
|
||||
```
|
||||
result1 >>> {
|
||||
// executed on success
|
||||
return ?
|
||||
}
|
||||
```
|
||||
|
||||
_`>==` and `>>>` were chosen because they are the closest sequence of characters to standard monadic bind `>>=` and `>>` function.
|
||||
`>>!` was chosen because `!` is easily associated with error._
|
||||
|
||||
## Naming conventions and best practices
|
||||
|
||||
For every group of transforming functions there are versions with and without "OrDie" suffix.
|
||||
|
||||
e.g.
|
||||
|
||||
```
|
||||
public func mapOrDie<E, R>
|
||||
(selector: E -> Result<R>)
|
||||
-> (Observable<E> -> Observable<R>) {
|
||||
return { source in
|
||||
return selectOrDie(selector)(source)
|
||||
}
|
||||
}
|
||||
|
||||
public func map<E, R>
|
||||
(selector: E -> R)
|
||||
-> (Observable<E> -> Observable<R>) {
|
||||
return { source in
|
||||
return select(selector)(source)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Returning an error from a selector will cause entire graph of dependant sequence transformers to "die" and fail with error. Dying implies that it will release all of it's resources and never produce another sequence value. This is usually not an obvious effect.
|
||||
|
||||
If there is some UITextField bound to a observable sequence that fails with error or completes, screen won't be updated ever again.
|
||||
|
||||
To make those situations more obvious, RxCocoa will throw an exception in case some sequence that is bound to UI control terminates with an error.
|
||||
|
||||
Using functions without "OrDie" suffix is usually a preferred option.
|
||||
|
||||
Best practice would be to use `Result` enum as a `Element` type in observable sequence. This is how example app works. In that way, errors can be safely propagated to UI and observing sequences will continue to produce values in case of some transient server error.
|
||||
|
||||
## Peculiarities
|
||||
|
||||
* Swift support for generic enums is limited. That's why there is `Box` hack in `Result` and `Event` enums
|
||||
```
|
||||
unimplemented IR generation feature non-fixed multi-payload enum layout
|
||||
```
|
||||
* Swift compiler had troubles with curried functions in release mode
|
||||
```
|
||||
// These two functions are equivalent, although second option is more readable IMHO
|
||||
|
||||
public func map<E, R> // this is ok
|
||||
(selector: E -> R)
|
||||
-> (Observable<E> -> Observable<R>) {
|
||||
return { source in
|
||||
return select(selector)(source)
|
||||
}
|
||||
}
|
||||
|
||||
public func map<E, R> // this will cause crashes in release version
|
||||
(selector: E -> R) // of your program if >- operator is used
|
||||
(source: Observable<E>)
|
||||
-> Observable<R> {
|
||||
return select(selector)(source)
|
||||
}
|
||||
```
|
||||
|
|
@ -1,410 +0,0 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
C89C81931A87CCBF00AA00FF /* Rx.h in Headers */ = {isa = PBXBuildFile; fileRef = C89C81921A87CCBF00AA00FF /* Rx.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C89C81991A87CCBF00AA00FF /* Rx.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C89C818D1A87CCBF00AA00FF /* Rx.framework */; };
|
||||
C89C81A01A87CCBF00AA00FF /* RxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89C819F1A87CCBF00AA00FF /* RxTests.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
C89C819A1A87CCBF00AA00FF /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = C89C81841A87CCBF00AA00FF /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = C89C818C1A87CCBF00AA00FF;
|
||||
remoteInfo = Rx;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
C89C818D1A87CCBF00AA00FF /* Rx.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Rx.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C89C81911A87CCBF00AA00FF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
C89C81921A87CCBF00AA00FF /* Rx.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Rx.h; sourceTree = "<group>"; };
|
||||
C89C81981A87CCBF00AA00FF /* RxTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RxTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C89C819E1A87CCBF00AA00FF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
C89C819F1A87CCBF00AA00FF /* RxTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RxTests.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
C89C81891A87CCBF00AA00FF /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
C89C81951A87CCBF00AA00FF /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C89C81991A87CCBF00AA00FF /* Rx.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
C89C81831A87CCBF00AA00FF = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C89C818F1A87CCBF00AA00FF /* Rx */,
|
||||
C89C819C1A87CCBF00AA00FF /* RxTests */,
|
||||
C89C818E1A87CCBF00AA00FF /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C89C818E1A87CCBF00AA00FF /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C89C818D1A87CCBF00AA00FF /* Rx.framework */,
|
||||
C89C81981A87CCBF00AA00FF /* RxTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C89C818F1A87CCBF00AA00FF /* Rx */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C89C81921A87CCBF00AA00FF /* Rx.h */,
|
||||
C89C81901A87CCBF00AA00FF /* Supporting Files */,
|
||||
);
|
||||
path = Rx;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C89C81901A87CCBF00AA00FF /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C89C81911A87CCBF00AA00FF /* Info.plist */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C89C819C1A87CCBF00AA00FF /* RxTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C89C819F1A87CCBF00AA00FF /* RxTests.swift */,
|
||||
C89C819D1A87CCBF00AA00FF /* Supporting Files */,
|
||||
);
|
||||
path = RxTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C89C819D1A87CCBF00AA00FF /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C89C819E1A87CCBF00AA00FF /* Info.plist */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
C89C818A1A87CCBF00AA00FF /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C89C81931A87CCBF00AA00FF /* Rx.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
C89C818C1A87CCBF00AA00FF /* Rx */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = C89C81A31A87CCBF00AA00FF /* Build configuration list for PBXNativeTarget "Rx" */;
|
||||
buildPhases = (
|
||||
C89C81881A87CCBF00AA00FF /* Sources */,
|
||||
C89C81891A87CCBF00AA00FF /* Frameworks */,
|
||||
C89C818A1A87CCBF00AA00FF /* Headers */,
|
||||
C89C818B1A87CCBF00AA00FF /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Rx;
|
||||
productName = Rx;
|
||||
productReference = C89C818D1A87CCBF00AA00FF /* Rx.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
C89C81971A87CCBF00AA00FF /* RxTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = C89C81A61A87CCBF00AA00FF /* Build configuration list for PBXNativeTarget "RxTests" */;
|
||||
buildPhases = (
|
||||
C89C81941A87CCBF00AA00FF /* Sources */,
|
||||
C89C81951A87CCBF00AA00FF /* Frameworks */,
|
||||
C89C81961A87CCBF00AA00FF /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
C89C819B1A87CCBF00AA00FF /* PBXTargetDependency */,
|
||||
);
|
||||
name = RxTests;
|
||||
productName = RxTests;
|
||||
productReference = C89C81981A87CCBF00AA00FF /* RxTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
C89C81841A87CCBF00AA00FF /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0610;
|
||||
ORGANIZATIONNAME = "Krunoslav Zaher";
|
||||
TargetAttributes = {
|
||||
C89C818C1A87CCBF00AA00FF = {
|
||||
CreatedOnToolsVersion = 6.1.1;
|
||||
};
|
||||
C89C81971A87CCBF00AA00FF = {
|
||||
CreatedOnToolsVersion = 6.1.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = C89C81871A87CCBF00AA00FF /* Build configuration list for PBXProject "Rx" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = C89C81831A87CCBF00AA00FF;
|
||||
productRefGroup = C89C818E1A87CCBF00AA00FF /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
C89C818C1A87CCBF00AA00FF /* Rx */,
|
||||
C89C81971A87CCBF00AA00FF /* RxTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
C89C818B1A87CCBF00AA00FF /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
C89C81961A87CCBF00AA00FF /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
C89C81881A87CCBF00AA00FF /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
C89C81941A87CCBF00AA00FF /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C89C81A01A87CCBF00AA00FF /* RxTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
C89C819B1A87CCBF00AA00FF /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = C89C818C1A87CCBF00AA00FF /* Rx */;
|
||||
targetProxy = C89C819A1A87CCBF00AA00FF /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
C89C81A11A87CCBF00AA00FF /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
C89C81A21A87CCBF00AA00FF /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
C89C81A41A87CCBF00AA00FF /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = Rx/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
C89C81A51A87CCBF00AA00FF /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = Rx/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
C89C81A71A87CCBF00AA00FF /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = RxTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
C89C81A81A87CCBF00AA00FF /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = RxTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
C89C81871A87CCBF00AA00FF /* Build configuration list for PBXProject "Rx" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
C89C81A11A87CCBF00AA00FF /* Debug */,
|
||||
C89C81A21A87CCBF00AA00FF /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
C89C81A31A87CCBF00AA00FF /* Build configuration list for PBXNativeTarget "Rx" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
C89C81A41A87CCBF00AA00FF /* Debug */,
|
||||
C89C81A51A87CCBF00AA00FF /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
};
|
||||
C89C81A61A87CCBF00AA00FF /* Build configuration list for PBXNativeTarget "RxTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
C89C81A71A87CCBF00AA00FF /* Debug */,
|
||||
C89C81A81A87CCBF00AA00FF /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = C89C81841A87CCBF00AA00FF /* Project object */;
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:LICENSE.md">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:README.md">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Rx/Rx.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:RxCocoa/RxCocoa.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:RxExample/RxExample.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDESourceControlProjectFavoriteDictionaryKey</key>
|
||||
<false/>
|
||||
<key>IDESourceControlProjectIdentifier</key>
|
||||
<string>0AB0D228-3687-496F-A331-96D92DCCD648</string>
|
||||
<key>IDESourceControlProjectName</key>
|
||||
<string>Rx</string>
|
||||
<key>IDESourceControlProjectOriginsDictionary</key>
|
||||
<dict>
|
||||
<key>8B123162C394A0A0A138779108E4C59DD771865A</key>
|
||||
<string>github.com:kzaher/RxSwift.git</string>
|
||||
</dict>
|
||||
<key>IDESourceControlProjectPath</key>
|
||||
<string>Rx.xcworkspace</string>
|
||||
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
|
||||
<dict>
|
||||
<key>8B123162C394A0A0A138779108E4C59DD771865A</key>
|
||||
<string>..</string>
|
||||
</dict>
|
||||
<key>IDESourceControlProjectURL</key>
|
||||
<string>github.com:kzaher/RxSwift.git</string>
|
||||
<key>IDESourceControlProjectVersion</key>
|
||||
<integer>111</integer>
|
||||
<key>IDESourceControlProjectWCCIdentifier</key>
|
||||
<string>8B123162C394A0A0A138779108E4C59DD771865A</string>
|
||||
<key>IDESourceControlProjectWCConfigurations</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
|
||||
<string>public.vcs.git</string>
|
||||
<key>IDESourceControlWCCIdentifierKey</key>
|
||||
<string>8B123162C394A0A0A138779108E4C59DD771865A</string>
|
||||
<key>IDESourceControlWCCName</key>
|
||||
<string>Rx</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges</key>
|
||||
<true/>
|
||||
<key>SnapshotAutomaticallyBeforeSignificantChanges</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Bucket
|
||||
type = "0"
|
||||
version = "2.0">
|
||||
<Breakpoints>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.ExceptionBreakpoint">
|
||||
<BreakpointContent
|
||||
shouldBeEnabled = "Yes"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
scope = "0"
|
||||
stopOnStyle = "0">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
shouldBeEnabled = "Yes"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Rx/Rx/Observables/Observable/ObserveOn.swift"
|
||||
timestampString = "449882338.597056"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "38"
|
||||
endingLineNumber = "38"
|
||||
landmarkName = "on(_:)"
|
||||
landmarkType = "5">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
</Breakpoints>
|
||||
</Bucket>
|
||||
|
|
@ -0,0 +1,875 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
C815540C1A990D0C00C63152 /* SafeObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = C815540B1A990D0C00C63152 /* SafeObserver.swift */; };
|
||||
C81554161A990E1F00C63152 /* AnonymousObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = C81554121A990E1F00C63152 /* AnonymousObserver.swift */; };
|
||||
C81554171A990E1F00C63152 /* AutoDetachObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = C81554131A990E1F00C63152 /* AutoDetachObserver.swift */; };
|
||||
C81554181A990E1F00C63152 /* ObserverBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = C81554141A990E1F00C63152 /* ObserverBase.swift */; };
|
||||
C815541B1A990E3B00C63152 /* DisposedObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = C815541A1A990E3B00C63152 /* DisposedObserver.swift */; };
|
||||
C815541D1A990E5000C63152 /* DoneObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = C815541C1A990E5000C63152 /* DoneObserver.swift */; };
|
||||
C815541F1A990E7100C63152 /* NopObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = C815541E1A990E7100C63152 /* NopObserver.swift */; };
|
||||
C81554211A990E8E00C63152 /* AnonymousSafeObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = C81554201A990E8E00C63152 /* AnonymousSafeObserver.swift */; };
|
||||
C81554251A9925DA00C63152 /* Observable+Subscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = C81554241A9925DA00C63152 /* Observable+Subscription.swift */; };
|
||||
C81C49E01AC3556A001D7A5E /* DisposeBag.swift in Sources */ = {isa = PBXBuildFile; fileRef = C81C49DF1AC3556A001D7A5E /* DisposeBag.swift */; };
|
||||
C81C58D41A8D3A9A008A4301 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = C81C58D31A8D3A9A008A4301 /* Result.swift */; };
|
||||
C83270981AB4725800618D46 /* ColdObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C83270971AB4725800618D46 /* ColdObservable.swift */; };
|
||||
C832709A1AB4727500618D46 /* Observable.Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C83270991AB4727500618D46 /* Observable.Extensions.swift */; };
|
||||
C8336D211AB849CB00B8F943 /* Observable+Binding.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8336D0C1AB849CB00B8F943 /* Observable+Binding.swift */; };
|
||||
C8336D221AB849CB00B8F943 /* Observable+Concurrency.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8336D0D1AB849CB00B8F943 /* Observable+Concurrency.swift */; };
|
||||
C8336D231AB849CB00B8F943 /* Observable+Multiple.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8336D0E1AB849CB00B8F943 /* Observable+Multiple.swift */; };
|
||||
C8336D241AB849CB00B8F943 /* Observable+Single.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8336D0F1AB849CB00B8F943 /* Observable+Single.swift */; };
|
||||
C8336D251AB849CB00B8F943 /* Observable+StandardSequenceOperators.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8336D101AB849CB00B8F943 /* Observable+StandardSequenceOperators.swift */; };
|
||||
C8649FBF1AB19476006984E1 /* SerialDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8649FBE1AB19476006984E1 /* SerialDisposable.swift */; };
|
||||
C8649FC11AB194F3006984E1 /* Cancelable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8649FC01AB194F3006984E1 /* Cancelable.swift */; };
|
||||
C864E0D81ACB288000C2013F /* Lock.swift in Sources */ = {isa = PBXBuildFile; fileRef = C864E0D71ACB288000C2013F /* Lock.swift */; };
|
||||
C86603571AA1E0A7000460BD /* ObserverOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = C86603561AA1E0A7000460BD /* ObserverOf.swift */; };
|
||||
C86705251AA38D190048B3D5 /* Observable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C86705241AA38D190048B3D5 /* Observable.swift */; };
|
||||
C86D1DE51ABD843A00F4308D /* Observable+Creation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C86D1DE41ABD843A00F4308D /* Observable+Creation.swift */; };
|
||||
C86D1DE71ABD846D00F4308D /* SchedulerDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = C86D1DE61ABD846D00F4308D /* SchedulerDefaults.swift */; };
|
||||
C86D6D761A8F88D2003BDD7C /* Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = C86D6D751A8F88D2003BDD7C /* Rx.swift */; };
|
||||
C86D6D851A8FB8F3003BDD7C /* ConcurrencyTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C86D6D801A8FB8F3003BDD7C /* ConcurrencyTest.swift */; };
|
||||
C86D6D861A8FB8F3003BDD7C /* DisposableTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C86D6D811A8FB8F3003BDD7C /* DisposableTest.swift */; };
|
||||
C86D6D871A8FB8F3003BDD7C /* Observable+SingleTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C86D6D821A8FB8F3003BDD7C /* Observable+SingleTest.swift */; };
|
||||
C86D6D881A8FB8F3003BDD7C /* RxTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C86D6D831A8FB8F3003BDD7C /* RxTest.swift */; };
|
||||
C8754A201A97D65E00BE09AD /* CompositeDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8754A1F1A97D65E00BE09AD /* CompositeDisposable.swift */; };
|
||||
C8781B841A93EBE40028125F /* Observable+StandardSequenceOperatorsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8781B831A93EBE40028125F /* Observable+StandardSequenceOperatorsTest.swift */; };
|
||||
C8813D7A1AD12D3E0072A050 /* Aggregate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D631AD12D3E0072A050 /* Aggregate.swift */; };
|
||||
C8813D7B1AD12D3E0072A050 /* AnonymousObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D641AD12D3E0072A050 /* AnonymousObservable.swift */; };
|
||||
C8813D7C1AD12D3E0072A050 /* AsObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D651AD12D3E0072A050 /* AsObservable.swift */; };
|
||||
C8813D7D1AD12D3E0072A050 /* CombineLatest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D661AD12D3E0072A050 /* CombineLatest.swift */; };
|
||||
C8813D7E1AD12D3E0072A050 /* Concat.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D671AD12D3E0072A050 /* Concat.swift */; };
|
||||
C8813D7F1AD12D3E0072A050 /* ConcatSink.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D681AD12D3E0072A050 /* ConcatSink.swift */; };
|
||||
C8813D801AD12D3E0072A050 /* ConnectableObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D691AD12D3E0072A050 /* ConnectableObservable.swift */; };
|
||||
C8813D811AD12D3E0072A050 /* DistinctUntilChanged.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D6A1AD12D3E0072A050 /* DistinctUntilChanged.swift */; };
|
||||
C8813D821AD12D3E0072A050 /* Do.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D6B1AD12D3E0072A050 /* Do.swift */; };
|
||||
C8813D831AD12D3E0072A050 /* Merge.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D6C1AD12D3E0072A050 /* Merge.swift */; };
|
||||
C8813D841AD12D3E0072A050 /* Multicast.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D6D1AD12D3E0072A050 /* Multicast.swift */; };
|
||||
C8813D851AD12D3E0072A050 /* ObservableBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D6E1AD12D3E0072A050 /* ObservableBase.swift */; };
|
||||
C8813D861AD12D3E0072A050 /* ObserveSingleOn.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D6F1AD12D3E0072A050 /* ObserveSingleOn.swift */; };
|
||||
C8813D871AD12D3E0072A050 /* Producer.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D701AD12D3E0072A050 /* Producer.swift */; };
|
||||
C8813D881AD12D3E0072A050 /* RefCount.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D711AD12D3E0072A050 /* RefCount.swift */; };
|
||||
C8813D891AD12D3E0072A050 /* Select.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D721AD12D3E0072A050 /* Select.swift */; };
|
||||
C8813D8A1AD12D3E0072A050 /* Sink.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D731AD12D3E0072A050 /* Sink.swift */; };
|
||||
C8813D8B1AD12D3E0072A050 /* Subject.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D741AD12D3E0072A050 /* Subject.swift */; };
|
||||
C8813D8C1AD12D3E0072A050 /* Switch.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D751AD12D3E0072A050 /* Switch.swift */; };
|
||||
C8813D8D1AD12D3E0072A050 /* TailRecursiveSink.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D761AD12D3E0072A050 /* TailRecursiveSink.swift */; };
|
||||
C8813D8E1AD12D3E0072A050 /* Throttle.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D771AD12D3E0072A050 /* Throttle.swift */; };
|
||||
C8813D8F1AD12D3E0072A050 /* Variable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D781AD12D3E0072A050 /* Variable.swift */; };
|
||||
C8813D901AD12D3E0072A050 /* WhereObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D791AD12D3E0072A050 /* WhereObservable.swift */; };
|
||||
C8813D921AD12D540072A050 /* ScheduledObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8813D911AD12D540072A050 /* ScheduledObserver.swift */; };
|
||||
C89094F91AD04995000E8322 /* OperationQueueScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89094F81AD04995000E8322 /* OperationQueueScheduler.swift */; };
|
||||
C89A2C6F1ACDAC6300CAF23E /* Observable+AggregateTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89A2C6E1ACDAC6300CAF23E /* Observable+AggregateTest.swift */; };
|
||||
C89C81931A87CCBF00AA00FF /* Rx.h in Headers */ = {isa = PBXBuildFile; fileRef = C89C81921A87CCBF00AA00FF /* Rx.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C89C81991A87CCBF00AA00FF /* Rx.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C89C818D1A87CCBF00AA00FF /* Rx.framework */; };
|
||||
C89C81B41A87CD0900AA00FF /* Disposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89C81AC1A87CD0900AA00FF /* Disposable.swift */; };
|
||||
C89C81B51A87CD0900AA00FF /* Event.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89C81AD1A87CD0900AA00FF /* Event.swift */; };
|
||||
C89C81B71A87CD0900AA00FF /* ObserverType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89C81AF1A87CD0900AA00FF /* ObserverType.swift */; };
|
||||
C89C81B81A87CD0900AA00FF /* Scheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89C81B11A87CD0900AA00FF /* Scheduler.swift */; };
|
||||
C89C81BE1A87E5BB00AA00FF /* MainScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89C81BD1A87E5BB00AA00FF /* MainScheduler.swift */; };
|
||||
C89C81C51A87F62900AA00FF /* DispatchQueueScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89C81C41A87F62900AA00FF /* DispatchQueueScheduler.swift */; };
|
||||
C8B7458E1ACF530A00C60106 /* DisposeBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8B7458D1ACF530A00C60106 /* DisposeBase.swift */; };
|
||||
C8B8D9801ABE069900652C5D /* QueueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8B8D97F1ABE069900652C5D /* QueueTests.swift */; };
|
||||
C8B8D9821ABEE98E00652C5D /* Observable+Time.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8B8D9811ABEE98E00652C5D /* Observable+Time.swift */; };
|
||||
C8B8D9861ABF28DF00652C5D /* Observable+Aggregate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8B8D9851ABF28DF00652C5D /* Observable+Aggregate.swift */; };
|
||||
C8B8D9901AC010B900652C5D /* AsyncLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8B8D98A1AC010B900652C5D /* AsyncLock.swift */; };
|
||||
C8B8D9931AC010B900652C5D /* Bag.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8B8D98E1AC010B900652C5D /* Bag.swift */; };
|
||||
C8B8D9941AC010B900652C5D /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8B8D98F1AC010B900652C5D /* Queue.swift */; };
|
||||
C8B8D9961AC0153C00652C5D /* Observable+TimeTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8B8D9951AC0153C00652C5D /* Observable+TimeTest.swift */; };
|
||||
C8C339CC1A90B5780016C6EB /* HotObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C339C31A90B5780016C6EB /* HotObservable.swift */; };
|
||||
C8C339CD1A90B5780016C6EB /* MockObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C339C41A90B5780016C6EB /* MockObserver.swift */; };
|
||||
C8C339CE1A90B5780016C6EB /* TestObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C339C51A90B5780016C6EB /* TestObservable.swift */; };
|
||||
C8C339CF1A90B5780016C6EB /* TestObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C339C61A90B5780016C6EB /* TestObserver.swift */; };
|
||||
C8C339D01A90B5780016C6EB /* Recorded.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C339C71A90B5780016C6EB /* Recorded.swift */; };
|
||||
C8C339D11A90B5780016C6EB /* TestScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C339C91A90B5780016C6EB /* TestScheduler.swift */; };
|
||||
C8C339D21A90B5780016C6EB /* VirtualTimeSchedulerBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C339CA1A90B5780016C6EB /* VirtualTimeSchedulerBase.swift */; };
|
||||
C8C339D31A90B5780016C6EB /* Subscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C339CB1A90B5780016C6EB /* Subscription.swift */; };
|
||||
C8C339D51A90B8620016C6EB /* TestExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C339D41A90B8620016C6EB /* TestExtensions.swift */; };
|
||||
C8C339D71A90B8B10016C6EB /* Observable+MultipleTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C339D61A90B8B10016C6EB /* Observable+MultipleTest.swift */; };
|
||||
C8C339DB1A90C3C20016C6EB /* ImmediateSchedulerOnCurrentThread.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C339DA1A90C3C20016C6EB /* ImmediateSchedulerOnCurrentThread.swift */; };
|
||||
C8C339E21A9129F00016C6EB /* SingleAssignmentDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C339E11A9129F00016C6EB /* SingleAssignmentDisposable.swift */; };
|
||||
C8C339E41A912ACD0016C6EB /* DefaultDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C339E31A912ACD0016C6EB /* DefaultDisposable.swift */; };
|
||||
C8C43C461AA3A58A00CFEC97 /* ConnectableObservableType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C43C451AA3A58A00CFEC97 /* ConnectableObservableType.swift */; };
|
||||
C8C43C481AA3A5C600CFEC97 /* SubjectType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C43C471AA3A5C600CFEC97 /* SubjectType.swift */; };
|
||||
C8D26ED51A914DA40067C793 /* AnonymousDisposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8D26ED41A914DA40067C793 /* AnonymousDisposable.swift */; };
|
||||
C8DB02A21A8FD69100B7FE90 /* AssumptionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8DB02A11A8FD69100B7FE90 /* AssumptionsTest.swift */; };
|
||||
C8DDCFC91AC6CA2A00414017 /* AnyObject+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8DDCFC81AC6CA2A00414017 /* AnyObject+Rx.swift */; };
|
||||
C8DDCFCB1AC6CA5500414017 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8DDCFCA1AC6CA5500414017 /* Error.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
C89C819A1A87CCBF00AA00FF /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = C89C81841A87CCBF00AA00FF /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = C89C818C1A87CCBF00AA00FF;
|
||||
remoteInfo = Rx;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
C815540B1A990D0C00C63152 /* SafeObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SafeObserver.swift; sourceTree = "<group>"; };
|
||||
C81554121A990E1F00C63152 /* AnonymousObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = AnonymousObserver.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
||||
C81554131A990E1F00C63152 /* AutoDetachObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AutoDetachObserver.swift; sourceTree = "<group>"; };
|
||||
C81554141A990E1F00C63152 /* ObserverBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObserverBase.swift; sourceTree = "<group>"; };
|
||||
C815541A1A990E3B00C63152 /* DisposedObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DisposedObserver.swift; sourceTree = "<group>"; };
|
||||
C815541C1A990E5000C63152 /* DoneObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DoneObserver.swift; sourceTree = "<group>"; };
|
||||
C815541E1A990E7100C63152 /* NopObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NopObserver.swift; sourceTree = "<group>"; };
|
||||
C81554201A990E8E00C63152 /* AnonymousSafeObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = AnonymousSafeObserver.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
||||
C81554241A9925DA00C63152 /* Observable+Subscription.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Observable+Subscription.swift"; sourceTree = "<group>"; };
|
||||
C81C49DF1AC3556A001D7A5E /* DisposeBag.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DisposeBag.swift; sourceTree = "<group>"; };
|
||||
C81C58D31A8D3A9A008A4301 /* Result.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Result.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
||||
C83270971AB4725800618D46 /* ColdObservable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColdObservable.swift; sourceTree = "<group>"; };
|
||||
C83270991AB4727500618D46 /* Observable.Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Observable.Extensions.swift; sourceTree = "<group>"; };
|
||||
C8336D0C1AB849CB00B8F943 /* Observable+Binding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Observable+Binding.swift"; sourceTree = "<group>"; };
|
||||
C8336D0D1AB849CB00B8F943 /* Observable+Concurrency.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Observable+Concurrency.swift"; sourceTree = "<group>"; };
|
||||
C8336D0E1AB849CB00B8F943 /* Observable+Multiple.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Observable+Multiple.swift"; sourceTree = "<group>"; };
|
||||
C8336D0F1AB849CB00B8F943 /* Observable+Single.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Observable+Single.swift"; sourceTree = "<group>"; };
|
||||
C8336D101AB849CB00B8F943 /* Observable+StandardSequenceOperators.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Observable+StandardSequenceOperators.swift"; sourceTree = "<group>"; };
|
||||
C86217FB1A8D650800985A9C /* Rx.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Rx.pch; sourceTree = "<group>"; };
|
||||
C8649FBE1AB19476006984E1 /* SerialDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SerialDisposable.swift; sourceTree = "<group>"; };
|
||||
C8649FC01AB194F3006984E1 /* Cancelable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cancelable.swift; sourceTree = "<group>"; };
|
||||
C864E0D71ACB288000C2013F /* Lock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Lock.swift; sourceTree = "<group>"; };
|
||||
C86603561AA1E0A7000460BD /* ObserverOf.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObserverOf.swift; sourceTree = "<group>"; };
|
||||
C86705241AA38D190048B3D5 /* Observable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Observable.swift; sourceTree = "<group>"; };
|
||||
C86D1DE41ABD843A00F4308D /* Observable+Creation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Observable+Creation.swift"; sourceTree = "<group>"; };
|
||||
C86D1DE61ABD846D00F4308D /* SchedulerDefaults.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchedulerDefaults.swift; sourceTree = "<group>"; };
|
||||
C86D6D751A8F88D2003BDD7C /* Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Rx.swift; sourceTree = "<group>"; };
|
||||
C86D6D801A8FB8F3003BDD7C /* ConcurrencyTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConcurrencyTest.swift; sourceTree = "<group>"; };
|
||||
C86D6D811A8FB8F3003BDD7C /* DisposableTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DisposableTest.swift; sourceTree = "<group>"; };
|
||||
C86D6D821A8FB8F3003BDD7C /* Observable+SingleTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Observable+SingleTest.swift"; sourceTree = "<group>"; };
|
||||
C86D6D831A8FB8F3003BDD7C /* RxTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxTest.swift; sourceTree = "<group>"; };
|
||||
C8754A1F1A97D65E00BE09AD /* CompositeDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompositeDisposable.swift; sourceTree = "<group>"; };
|
||||
C8781B831A93EBE40028125F /* Observable+StandardSequenceOperatorsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Observable+StandardSequenceOperatorsTest.swift"; sourceTree = "<group>"; };
|
||||
C8813D631AD12D3E0072A050 /* Aggregate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Aggregate.swift; sourceTree = "<group>"; };
|
||||
C8813D641AD12D3E0072A050 /* AnonymousObservable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnonymousObservable.swift; sourceTree = "<group>"; };
|
||||
C8813D651AD12D3E0072A050 /* AsObservable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsObservable.swift; sourceTree = "<group>"; };
|
||||
C8813D661AD12D3E0072A050 /* CombineLatest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CombineLatest.swift; sourceTree = "<group>"; };
|
||||
C8813D671AD12D3E0072A050 /* Concat.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Concat.swift; sourceTree = "<group>"; };
|
||||
C8813D681AD12D3E0072A050 /* ConcatSink.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConcatSink.swift; sourceTree = "<group>"; };
|
||||
C8813D691AD12D3E0072A050 /* ConnectableObservable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectableObservable.swift; sourceTree = "<group>"; };
|
||||
C8813D6A1AD12D3E0072A050 /* DistinctUntilChanged.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DistinctUntilChanged.swift; sourceTree = "<group>"; };
|
||||
C8813D6B1AD12D3E0072A050 /* Do.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Do.swift; sourceTree = "<group>"; };
|
||||
C8813D6C1AD12D3E0072A050 /* Merge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Merge.swift; sourceTree = "<group>"; };
|
||||
C8813D6D1AD12D3E0072A050 /* Multicast.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Multicast.swift; sourceTree = "<group>"; };
|
||||
C8813D6E1AD12D3E0072A050 /* ObservableBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObservableBase.swift; sourceTree = "<group>"; };
|
||||
C8813D6F1AD12D3E0072A050 /* ObserveSingleOn.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObserveSingleOn.swift; sourceTree = "<group>"; };
|
||||
C8813D701AD12D3E0072A050 /* Producer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Producer.swift; sourceTree = "<group>"; };
|
||||
C8813D711AD12D3E0072A050 /* RefCount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RefCount.swift; sourceTree = "<group>"; };
|
||||
C8813D721AD12D3E0072A050 /* Select.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Select.swift; sourceTree = "<group>"; };
|
||||
C8813D731AD12D3E0072A050 /* Sink.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Sink.swift; sourceTree = "<group>"; };
|
||||
C8813D741AD12D3E0072A050 /* Subject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Subject.swift; sourceTree = "<group>"; };
|
||||
C8813D751AD12D3E0072A050 /* Switch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Switch.swift; sourceTree = "<group>"; };
|
||||
C8813D761AD12D3E0072A050 /* TailRecursiveSink.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TailRecursiveSink.swift; sourceTree = "<group>"; };
|
||||
C8813D771AD12D3E0072A050 /* Throttle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Throttle.swift; sourceTree = "<group>"; };
|
||||
C8813D781AD12D3E0072A050 /* Variable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Variable.swift; sourceTree = "<group>"; };
|
||||
C8813D791AD12D3E0072A050 /* WhereObservable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WhereObservable.swift; sourceTree = "<group>"; };
|
||||
C8813D911AD12D540072A050 /* ScheduledObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScheduledObserver.swift; sourceTree = "<group>"; };
|
||||
C89094F81AD04995000E8322 /* OperationQueueScheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperationQueueScheduler.swift; sourceTree = "<group>"; };
|
||||
C89A2C6E1ACDAC6300CAF23E /* Observable+AggregateTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Observable+AggregateTest.swift"; sourceTree = "<group>"; };
|
||||
C89C818D1A87CCBF00AA00FF /* Rx.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Rx.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C89C81911A87CCBF00AA00FF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
C89C81921A87CCBF00AA00FF /* Rx.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Rx.h; sourceTree = "<group>"; };
|
||||
C89C81981A87CCBF00AA00FF /* RxTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RxTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C89C819E1A87CCBF00AA00FF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
C89C81AC1A87CD0900AA00FF /* Disposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Disposable.swift; sourceTree = "<group>"; };
|
||||
C89C81AD1A87CD0900AA00FF /* Event.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Event.swift; sourceTree = "<group>"; };
|
||||
C89C81AF1A87CD0900AA00FF /* ObserverType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ObserverType.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
||||
C89C81B11A87CD0900AA00FF /* Scheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Scheduler.swift; sourceTree = "<group>"; };
|
||||
C89C81BD1A87E5BB00AA00FF /* MainScheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainScheduler.swift; sourceTree = "<group>"; };
|
||||
C89C81C41A87F62900AA00FF /* DispatchQueueScheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DispatchQueueScheduler.swift; sourceTree = "<group>"; };
|
||||
C8B7458D1ACF530A00C60106 /* DisposeBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DisposeBase.swift; sourceTree = "<group>"; };
|
||||
C8B8D97F1ABE069900652C5D /* QueueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueueTests.swift; sourceTree = "<group>"; };
|
||||
C8B8D9811ABEE98E00652C5D /* Observable+Time.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Observable+Time.swift"; sourceTree = "<group>"; };
|
||||
C8B8D9851ABF28DF00652C5D /* Observable+Aggregate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Observable+Aggregate.swift"; sourceTree = "<group>"; };
|
||||
C8B8D98A1AC010B900652C5D /* AsyncLock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsyncLock.swift; sourceTree = "<group>"; };
|
||||
C8B8D98E1AC010B900652C5D /* Bag.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Bag.swift; sourceTree = "<group>"; };
|
||||
C8B8D98F1AC010B900652C5D /* Queue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Queue.swift; sourceTree = "<group>"; };
|
||||
C8B8D9951AC0153C00652C5D /* Observable+TimeTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Observable+TimeTest.swift"; sourceTree = "<group>"; };
|
||||
C8C339C31A90B5780016C6EB /* HotObservable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HotObservable.swift; sourceTree = "<group>"; };
|
||||
C8C339C41A90B5780016C6EB /* MockObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockObserver.swift; sourceTree = "<group>"; };
|
||||
C8C339C51A90B5780016C6EB /* TestObservable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestObservable.swift; sourceTree = "<group>"; };
|
||||
C8C339C61A90B5780016C6EB /* TestObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestObserver.swift; sourceTree = "<group>"; };
|
||||
C8C339C71A90B5780016C6EB /* Recorded.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Recorded.swift; sourceTree = "<group>"; };
|
||||
C8C339C91A90B5780016C6EB /* TestScheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestScheduler.swift; sourceTree = "<group>"; };
|
||||
C8C339CA1A90B5780016C6EB /* VirtualTimeSchedulerBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VirtualTimeSchedulerBase.swift; sourceTree = "<group>"; };
|
||||
C8C339CB1A90B5780016C6EB /* Subscription.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Subscription.swift; sourceTree = "<group>"; };
|
||||
C8C339D41A90B8620016C6EB /* TestExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestExtensions.swift; sourceTree = "<group>"; };
|
||||
C8C339D61A90B8B10016C6EB /* Observable+MultipleTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Observable+MultipleTest.swift"; sourceTree = "<group>"; };
|
||||
C8C339DA1A90C3C20016C6EB /* ImmediateSchedulerOnCurrentThread.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImmediateSchedulerOnCurrentThread.swift; sourceTree = "<group>"; };
|
||||
C8C339E11A9129F00016C6EB /* SingleAssignmentDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = SingleAssignmentDisposable.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
||||
C8C339E31A912ACD0016C6EB /* DefaultDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultDisposable.swift; sourceTree = "<group>"; };
|
||||
C8C43C451AA3A58A00CFEC97 /* ConnectableObservableType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectableObservableType.swift; sourceTree = "<group>"; };
|
||||
C8C43C471AA3A5C600CFEC97 /* SubjectType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubjectType.swift; sourceTree = "<group>"; };
|
||||
C8D26ED41A914DA40067C793 /* AnonymousDisposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnonymousDisposable.swift; sourceTree = "<group>"; };
|
||||
C8DB02A11A8FD69100B7FE90 /* AssumptionsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssumptionsTest.swift; sourceTree = "<group>"; };
|
||||
C8DDCFC81AC6CA2A00414017 /* AnyObject+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AnyObject+Rx.swift"; sourceTree = "<group>"; };
|
||||
C8DDCFCA1AC6CA5500414017 /* Error.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
C89C81891A87CCBF00AA00FF /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
C89C81951A87CCBF00AA00FF /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C89C81991A87CCBF00AA00FF /* Rx.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
C815540A1A990CFF00C63152 /* Observers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C81554121A990E1F00C63152 /* AnonymousObserver.swift */,
|
||||
C81554201A990E8E00C63152 /* AnonymousSafeObserver.swift */,
|
||||
C81554131A990E1F00C63152 /* AutoDetachObserver.swift */,
|
||||
C81554141A990E1F00C63152 /* ObserverBase.swift */,
|
||||
C815540B1A990D0C00C63152 /* SafeObserver.swift */,
|
||||
C815541A1A990E3B00C63152 /* DisposedObserver.swift */,
|
||||
C815541C1A990E5000C63152 /* DoneObserver.swift */,
|
||||
C815541E1A990E7100C63152 /* NopObserver.swift */,
|
||||
);
|
||||
path = Observers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C8336CFA1AB849CB00B8F943 /* Observables */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C8813D621AD12D3E0072A050 /* Implementations */,
|
||||
C8B8D9851ABF28DF00652C5D /* Observable+Aggregate.swift */,
|
||||
C8336D0C1AB849CB00B8F943 /* Observable+Binding.swift */,
|
||||
C8336D0D1AB849CB00B8F943 /* Observable+Concurrency.swift */,
|
||||
C86D1DE41ABD843A00F4308D /* Observable+Creation.swift */,
|
||||
C8336D0E1AB849CB00B8F943 /* Observable+Multiple.swift */,
|
||||
C8336D0F1AB849CB00B8F943 /* Observable+Single.swift */,
|
||||
C8336D101AB849CB00B8F943 /* Observable+StandardSequenceOperators.swift */,
|
||||
C8B8D9811ABEE98E00652C5D /* Observable+Time.swift */,
|
||||
);
|
||||
path = Observables;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C83AA0161A8A1DD500E0605C /* Disposables */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C8D26ED41A914DA40067C793 /* AnonymousDisposable.swift */,
|
||||
C8C339E11A9129F00016C6EB /* SingleAssignmentDisposable.swift */,
|
||||
C8C339E31A912ACD0016C6EB /* DefaultDisposable.swift */,
|
||||
C8754A1F1A97D65E00BE09AD /* CompositeDisposable.swift */,
|
||||
C8649FBE1AB19476006984E1 /* SerialDisposable.swift */,
|
||||
C81C49DF1AC3556A001D7A5E /* DisposeBag.swift */,
|
||||
C8B7458D1ACF530A00C60106 /* DisposeBase.swift */,
|
||||
);
|
||||
path = Disposables;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C86D6D7D1A8FB8F3003BDD7C /* TestImplementations */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C8C339C21A90B5780016C6EB /* Mocks */,
|
||||
C8C339C81A90B5780016C6EB /* Schedulers */,
|
||||
C8C339C71A90B5780016C6EB /* Recorded.swift */,
|
||||
C8C339CB1A90B5780016C6EB /* Subscription.swift */,
|
||||
C8C339D41A90B8620016C6EB /* TestExtensions.swift */,
|
||||
);
|
||||
path = TestImplementations;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C86D6D7F1A8FB8F3003BDD7C /* Tests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C8DB02A11A8FD69100B7FE90 /* AssumptionsTest.swift */,
|
||||
C86D6D801A8FB8F3003BDD7C /* ConcurrencyTest.swift */,
|
||||
C86D6D811A8FB8F3003BDD7C /* DisposableTest.swift */,
|
||||
C89A2C6E1ACDAC6300CAF23E /* Observable+AggregateTest.swift */,
|
||||
C8C339D61A90B8B10016C6EB /* Observable+MultipleTest.swift */,
|
||||
C86D6D821A8FB8F3003BDD7C /* Observable+SingleTest.swift */,
|
||||
C8781B831A93EBE40028125F /* Observable+StandardSequenceOperatorsTest.swift */,
|
||||
C8B8D9951AC0153C00652C5D /* Observable+TimeTest.swift */,
|
||||
C8B8D97F1ABE069900652C5D /* QueueTests.swift */,
|
||||
C86D6D831A8FB8F3003BDD7C /* RxTest.swift */,
|
||||
);
|
||||
path = Tests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C8813D621AD12D3E0072A050 /* Implementations */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C8813D631AD12D3E0072A050 /* Aggregate.swift */,
|
||||
C8813D641AD12D3E0072A050 /* AnonymousObservable.swift */,
|
||||
C8813D651AD12D3E0072A050 /* AsObservable.swift */,
|
||||
C8813D661AD12D3E0072A050 /* CombineLatest.swift */,
|
||||
C8813D671AD12D3E0072A050 /* Concat.swift */,
|
||||
C8813D681AD12D3E0072A050 /* ConcatSink.swift */,
|
||||
C8813D691AD12D3E0072A050 /* ConnectableObservable.swift */,
|
||||
C8813D6A1AD12D3E0072A050 /* DistinctUntilChanged.swift */,
|
||||
C8813D6B1AD12D3E0072A050 /* Do.swift */,
|
||||
C8813D6C1AD12D3E0072A050 /* Merge.swift */,
|
||||
C8813D6D1AD12D3E0072A050 /* Multicast.swift */,
|
||||
C8813D6E1AD12D3E0072A050 /* ObservableBase.swift */,
|
||||
C8813D6F1AD12D3E0072A050 /* ObserveSingleOn.swift */,
|
||||
C8813D701AD12D3E0072A050 /* Producer.swift */,
|
||||
C8813D711AD12D3E0072A050 /* RefCount.swift */,
|
||||
C8813D721AD12D3E0072A050 /* Select.swift */,
|
||||
C8813D731AD12D3E0072A050 /* Sink.swift */,
|
||||
C8813D741AD12D3E0072A050 /* Subject.swift */,
|
||||
C8813D751AD12D3E0072A050 /* Switch.swift */,
|
||||
C8813D761AD12D3E0072A050 /* TailRecursiveSink.swift */,
|
||||
C8813D771AD12D3E0072A050 /* Throttle.swift */,
|
||||
C8813D781AD12D3E0072A050 /* Variable.swift */,
|
||||
C8813D791AD12D3E0072A050 /* WhereObservable.swift */,
|
||||
C8813D911AD12D540072A050 /* ScheduledObserver.swift */,
|
||||
);
|
||||
path = Implementations;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C89C81831A87CCBF00AA00FF = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C89C818F1A87CCBF00AA00FF /* Rx */,
|
||||
C89C819C1A87CCBF00AA00FF /* RxTests */,
|
||||
C89C818E1A87CCBF00AA00FF /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C89C818E1A87CCBF00AA00FF /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C89C818D1A87CCBF00AA00FF /* Rx.framework */,
|
||||
C89C81981A87CCBF00AA00FF /* RxTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C89C818F1A87CCBF00AA00FF /* Rx */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C89C81921A87CCBF00AA00FF /* Rx.h */,
|
||||
C86D6D751A8F88D2003BDD7C /* Rx.swift */,
|
||||
C89C81AD1A87CD0900AA00FF /* Event.swift */,
|
||||
C8DDCFCA1AC6CA5500414017 /* Error.swift */,
|
||||
C81C58D31A8D3A9A008A4301 /* Result.swift */,
|
||||
C89C81AF1A87CD0900AA00FF /* ObserverType.swift */,
|
||||
C86603561AA1E0A7000460BD /* ObserverOf.swift */,
|
||||
C86705241AA38D190048B3D5 /* Observable.swift */,
|
||||
C89C81AC1A87CD0900AA00FF /* Disposable.swift */,
|
||||
C8649FC01AB194F3006984E1 /* Cancelable.swift */,
|
||||
C89C81B11A87CD0900AA00FF /* Scheduler.swift */,
|
||||
C8336CFA1AB849CB00B8F943 /* Observables */,
|
||||
C8B8D9891AC010B900652C5D /* Concurrency */,
|
||||
C8B8D98D1AC010B900652C5D /* DataStructures */,
|
||||
C89C81901A87CCBF00AA00FF /* Supporting Files */,
|
||||
C89C81B01A87CD0900AA00FF /* Scheduler */,
|
||||
C83AA0161A8A1DD500E0605C /* Disposables */,
|
||||
C815540A1A990CFF00C63152 /* Observers */,
|
||||
C8C43C441AA3A57B00CFEC97 /* Subjects */,
|
||||
C81554241A9925DA00C63152 /* Observable+Subscription.swift */,
|
||||
C8DDCFC81AC6CA2A00414017 /* AnyObject+Rx.swift */,
|
||||
);
|
||||
path = Rx;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C89C81901A87CCBF00AA00FF /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C89C81911A87CCBF00AA00FF /* Info.plist */,
|
||||
C86217FB1A8D650800985A9C /* Rx.pch */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C89C819C1A87CCBF00AA00FF /* RxTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C86D6D7D1A8FB8F3003BDD7C /* TestImplementations */,
|
||||
C86D6D7F1A8FB8F3003BDD7C /* Tests */,
|
||||
C89C819D1A87CCBF00AA00FF /* Supporting Files */,
|
||||
);
|
||||
path = RxTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C89C819D1A87CCBF00AA00FF /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C89C819E1A87CCBF00AA00FF /* Info.plist */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C89C81B01A87CD0900AA00FF /* Scheduler */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C86D1DE61ABD846D00F4308D /* SchedulerDefaults.swift */,
|
||||
C89C81BD1A87E5BB00AA00FF /* MainScheduler.swift */,
|
||||
C89C81C41A87F62900AA00FF /* DispatchQueueScheduler.swift */,
|
||||
C8C339DA1A90C3C20016C6EB /* ImmediateSchedulerOnCurrentThread.swift */,
|
||||
C89094F81AD04995000E8322 /* OperationQueueScheduler.swift */,
|
||||
);
|
||||
path = Scheduler;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C8B8D9891AC010B900652C5D /* Concurrency */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C8B8D98A1AC010B900652C5D /* AsyncLock.swift */,
|
||||
C864E0D71ACB288000C2013F /* Lock.swift */,
|
||||
);
|
||||
path = Concurrency;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C8B8D98D1AC010B900652C5D /* DataStructures */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C8B8D98E1AC010B900652C5D /* Bag.swift */,
|
||||
C8B8D98F1AC010B900652C5D /* Queue.swift */,
|
||||
);
|
||||
path = DataStructures;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C8C339C21A90B5780016C6EB /* Mocks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C8C339C31A90B5780016C6EB /* HotObservable.swift */,
|
||||
C83270971AB4725800618D46 /* ColdObservable.swift */,
|
||||
C8C339C41A90B5780016C6EB /* MockObserver.swift */,
|
||||
C8C339C51A90B5780016C6EB /* TestObservable.swift */,
|
||||
C8C339C61A90B5780016C6EB /* TestObserver.swift */,
|
||||
C83270991AB4727500618D46 /* Observable.Extensions.swift */,
|
||||
);
|
||||
path = Mocks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C8C339C81A90B5780016C6EB /* Schedulers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C8C339C91A90B5780016C6EB /* TestScheduler.swift */,
|
||||
C8C339CA1A90B5780016C6EB /* VirtualTimeSchedulerBase.swift */,
|
||||
);
|
||||
path = Schedulers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C8C43C441AA3A57B00CFEC97 /* Subjects */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C8C43C451AA3A58A00CFEC97 /* ConnectableObservableType.swift */,
|
||||
C8C43C471AA3A5C600CFEC97 /* SubjectType.swift */,
|
||||
);
|
||||
path = Subjects;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
C89C818A1A87CCBF00AA00FF /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C89C81931A87CCBF00AA00FF /* Rx.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
C89C818C1A87CCBF00AA00FF /* Rx */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = C89C81A31A87CCBF00AA00FF /* Build configuration list for PBXNativeTarget "Rx" */;
|
||||
buildPhases = (
|
||||
C89C81881A87CCBF00AA00FF /* Sources */,
|
||||
C89C81891A87CCBF00AA00FF /* Frameworks */,
|
||||
C89C818A1A87CCBF00AA00FF /* Headers */,
|
||||
C89C818B1A87CCBF00AA00FF /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Rx;
|
||||
productName = Rx;
|
||||
productReference = C89C818D1A87CCBF00AA00FF /* Rx.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
C89C81971A87CCBF00AA00FF /* RxTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = C89C81A61A87CCBF00AA00FF /* Build configuration list for PBXNativeTarget "RxTests" */;
|
||||
buildPhases = (
|
||||
C89C81941A87CCBF00AA00FF /* Sources */,
|
||||
C89C81951A87CCBF00AA00FF /* Frameworks */,
|
||||
C89C81961A87CCBF00AA00FF /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
C89C819B1A87CCBF00AA00FF /* PBXTargetDependency */,
|
||||
);
|
||||
name = RxTests;
|
||||
productName = RxTests;
|
||||
productReference = C89C81981A87CCBF00AA00FF /* RxTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
C89C81841A87CCBF00AA00FF /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0610;
|
||||
ORGANIZATIONNAME = "Krunoslav Zaher";
|
||||
TargetAttributes = {
|
||||
C89C818C1A87CCBF00AA00FF = {
|
||||
CreatedOnToolsVersion = 6.1.1;
|
||||
};
|
||||
C89C81971A87CCBF00AA00FF = {
|
||||
CreatedOnToolsVersion = 6.1.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = C89C81871A87CCBF00AA00FF /* Build configuration list for PBXProject "Rx" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = C89C81831A87CCBF00AA00FF;
|
||||
productRefGroup = C89C818E1A87CCBF00AA00FF /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
C89C818C1A87CCBF00AA00FF /* Rx */,
|
||||
C89C81971A87CCBF00AA00FF /* RxTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
C89C818B1A87CCBF00AA00FF /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
C89C81961A87CCBF00AA00FF /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
C89C81881A87CCBF00AA00FF /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C8DDCFC91AC6CA2A00414017 /* AnyObject+Rx.swift in Sources */,
|
||||
C89C81B51A87CD0900AA00FF /* Event.swift in Sources */,
|
||||
C8813D7B1AD12D3E0072A050 /* AnonymousObservable.swift in Sources */,
|
||||
C8813D821AD12D3E0072A050 /* Do.swift in Sources */,
|
||||
C89C81C51A87F62900AA00FF /* DispatchQueueScheduler.swift in Sources */,
|
||||
C89094F91AD04995000E8322 /* OperationQueueScheduler.swift in Sources */,
|
||||
C81554251A9925DA00C63152 /* Observable+Subscription.swift in Sources */,
|
||||
C8C43C461AA3A58A00CFEC97 /* ConnectableObservableType.swift in Sources */,
|
||||
C86D1DE51ABD843A00F4308D /* Observable+Creation.swift in Sources */,
|
||||
C86603571AA1E0A7000460BD /* ObserverOf.swift in Sources */,
|
||||
C89C81B81A87CD0900AA00FF /* Scheduler.swift in Sources */,
|
||||
C8813D8D1AD12D3E0072A050 /* TailRecursiveSink.swift in Sources */,
|
||||
C8813D8A1AD12D3E0072A050 /* Sink.swift in Sources */,
|
||||
C8B8D9901AC010B900652C5D /* AsyncLock.swift in Sources */,
|
||||
C86705251AA38D190048B3D5 /* Observable.swift in Sources */,
|
||||
C89C81B71A87CD0900AA00FF /* ObserverType.swift in Sources */,
|
||||
C81C58D41A8D3A9A008A4301 /* Result.swift in Sources */,
|
||||
C8C339DB1A90C3C20016C6EB /* ImmediateSchedulerOnCurrentThread.swift in Sources */,
|
||||
C8C43C481AA3A5C600CFEC97 /* SubjectType.swift in Sources */,
|
||||
C86D1DE71ABD846D00F4308D /* SchedulerDefaults.swift in Sources */,
|
||||
C8C339E41A912ACD0016C6EB /* DefaultDisposable.swift in Sources */,
|
||||
C81554171A990E1F00C63152 /* AutoDetachObserver.swift in Sources */,
|
||||
C8C339E21A9129F00016C6EB /* SingleAssignmentDisposable.swift in Sources */,
|
||||
C8813D851AD12D3E0072A050 /* ObservableBase.swift in Sources */,
|
||||
C8B8D9941AC010B900652C5D /* Queue.swift in Sources */,
|
||||
C8336D231AB849CB00B8F943 /* Observable+Multiple.swift in Sources */,
|
||||
C815541D1A990E5000C63152 /* DoneObserver.swift in Sources */,
|
||||
C81554161A990E1F00C63152 /* AnonymousObserver.swift in Sources */,
|
||||
C8649FBF1AB19476006984E1 /* SerialDisposable.swift in Sources */,
|
||||
C8B8D9861ABF28DF00652C5D /* Observable+Aggregate.swift in Sources */,
|
||||
C89C81BE1A87E5BB00AA00FF /* MainScheduler.swift in Sources */,
|
||||
C8336D221AB849CB00B8F943 /* Observable+Concurrency.swift in Sources */,
|
||||
C815541B1A990E3B00C63152 /* DisposedObserver.swift in Sources */,
|
||||
C8813D901AD12D3E0072A050 /* WhereObservable.swift in Sources */,
|
||||
C815540C1A990D0C00C63152 /* SafeObserver.swift in Sources */,
|
||||
C8813D7C1AD12D3E0072A050 /* AsObservable.swift in Sources */,
|
||||
C8813D8C1AD12D3E0072A050 /* Switch.swift in Sources */,
|
||||
C8813D7A1AD12D3E0072A050 /* Aggregate.swift in Sources */,
|
||||
C8649FC11AB194F3006984E1 /* Cancelable.swift in Sources */,
|
||||
C8754A201A97D65E00BE09AD /* CompositeDisposable.swift in Sources */,
|
||||
C8813D8F1AD12D3E0072A050 /* Variable.swift in Sources */,
|
||||
C8813D921AD12D540072A050 /* ScheduledObserver.swift in Sources */,
|
||||
C8B8D9931AC010B900652C5D /* Bag.swift in Sources */,
|
||||
C86D6D761A8F88D2003BDD7C /* Rx.swift in Sources */,
|
||||
C81554181A990E1F00C63152 /* ObserverBase.swift in Sources */,
|
||||
C8813D831AD12D3E0072A050 /* Merge.swift in Sources */,
|
||||
C8D26ED51A914DA40067C793 /* AnonymousDisposable.swift in Sources */,
|
||||
C8813D7D1AD12D3E0072A050 /* CombineLatest.swift in Sources */,
|
||||
C8B8D9821ABEE98E00652C5D /* Observable+Time.swift in Sources */,
|
||||
C81C49E01AC3556A001D7A5E /* DisposeBag.swift in Sources */,
|
||||
C8336D211AB849CB00B8F943 /* Observable+Binding.swift in Sources */,
|
||||
C8B7458E1ACF530A00C60106 /* DisposeBase.swift in Sources */,
|
||||
C8813D7E1AD12D3E0072A050 /* Concat.swift in Sources */,
|
||||
C8813D7F1AD12D3E0072A050 /* ConcatSink.swift in Sources */,
|
||||
C8813D861AD12D3E0072A050 /* ObserveSingleOn.swift in Sources */,
|
||||
C8813D841AD12D3E0072A050 /* Multicast.swift in Sources */,
|
||||
C8336D251AB849CB00B8F943 /* Observable+StandardSequenceOperators.swift in Sources */,
|
||||
C8336D241AB849CB00B8F943 /* Observable+Single.swift in Sources */,
|
||||
C8813D8E1AD12D3E0072A050 /* Throttle.swift in Sources */,
|
||||
C81554211A990E8E00C63152 /* AnonymousSafeObserver.swift in Sources */,
|
||||
C8813D801AD12D3E0072A050 /* ConnectableObservable.swift in Sources */,
|
||||
C89C81B41A87CD0900AA00FF /* Disposable.swift in Sources */,
|
||||
C8813D8B1AD12D3E0072A050 /* Subject.swift in Sources */,
|
||||
C864E0D81ACB288000C2013F /* Lock.swift in Sources */,
|
||||
C815541F1A990E7100C63152 /* NopObserver.swift in Sources */,
|
||||
C8813D871AD12D3E0072A050 /* Producer.swift in Sources */,
|
||||
C8DDCFCB1AC6CA5500414017 /* Error.swift in Sources */,
|
||||
C8813D891AD12D3E0072A050 /* Select.swift in Sources */,
|
||||
C8813D881AD12D3E0072A050 /* RefCount.swift in Sources */,
|
||||
C8813D811AD12D3E0072A050 /* DistinctUntilChanged.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
C89C81941A87CCBF00AA00FF /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C8C339D21A90B5780016C6EB /* VirtualTimeSchedulerBase.swift in Sources */,
|
||||
C89A2C6F1ACDAC6300CAF23E /* Observable+AggregateTest.swift in Sources */,
|
||||
C86D6D871A8FB8F3003BDD7C /* Observable+SingleTest.swift in Sources */,
|
||||
C86D6D861A8FB8F3003BDD7C /* DisposableTest.swift in Sources */,
|
||||
C8C339CE1A90B5780016C6EB /* TestObservable.swift in Sources */,
|
||||
C8C339D31A90B5780016C6EB /* Subscription.swift in Sources */,
|
||||
C8DB02A21A8FD69100B7FE90 /* AssumptionsTest.swift in Sources */,
|
||||
C832709A1AB4727500618D46 /* Observable.Extensions.swift in Sources */,
|
||||
C8B8D9801ABE069900652C5D /* QueueTests.swift in Sources */,
|
||||
C8B8D9961AC0153C00652C5D /* Observable+TimeTest.swift in Sources */,
|
||||
C8781B841A93EBE40028125F /* Observable+StandardSequenceOperatorsTest.swift in Sources */,
|
||||
C83270981AB4725800618D46 /* ColdObservable.swift in Sources */,
|
||||
C8C339D11A90B5780016C6EB /* TestScheduler.swift in Sources */,
|
||||
C8C339D01A90B5780016C6EB /* Recorded.swift in Sources */,
|
||||
C86D6D851A8FB8F3003BDD7C /* ConcurrencyTest.swift in Sources */,
|
||||
C8C339D51A90B8620016C6EB /* TestExtensions.swift in Sources */,
|
||||
C86D6D881A8FB8F3003BDD7C /* RxTest.swift in Sources */,
|
||||
C8C339D71A90B8B10016C6EB /* Observable+MultipleTest.swift in Sources */,
|
||||
C8C339CC1A90B5780016C6EB /* HotObservable.swift in Sources */,
|
||||
C8C339CD1A90B5780016C6EB /* MockObserver.swift in Sources */,
|
||||
C8C339CF1A90B5780016C6EB /* TestObserver.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
C89C819B1A87CCBF00AA00FF /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = C89C818C1A87CCBF00AA00FF /* Rx */;
|
||||
targetProxy = C89C819A1A87CCBF00AA00FF /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
C89C81A11A87CCBF00AA00FF /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_SWIFT_FLAGS = "-D USE_FUNCTIONAL_NAMES";
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
C89C81A21A87CCBF00AA00FF /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
OTHER_SWIFT_FLAGS = "-D USE_FUNCTIONAL_NAMES";
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
C89C81A41A87CCBF00AA00FF /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
GCC_PREFIX_HEADER = Rx/Rx.pch;
|
||||
INFOPLIST_FILE = Rx/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
OTHER_SWIFT_FLAGS = "-D USE_FUNCTIONAL_NAMES -D DEBUG";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
C89C81A51A87CCBF00AA00FF /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
GCC_PREFIX_HEADER = Rx/Rx.pch;
|
||||
INFOPLIST_FILE = Rx/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
C89C81A71A87CCBF00AA00FF /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = RxTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
OTHER_SWIFT_FLAGS = "-D USE_FUNCTIONAL_NAMES -D DEBUG";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
C89C81A81A87CCBF00AA00FF /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = RxTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
C89C81871A87CCBF00AA00FF /* Build configuration list for PBXProject "Rx" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
C89C81A11A87CCBF00AA00FF /* Debug */,
|
||||
C89C81A21A87CCBF00AA00FF /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
C89C81A31A87CCBF00AA00FF /* Build configuration list for PBXNativeTarget "Rx" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
C89C81A41A87CCBF00AA00FF /* Debug */,
|
||||
C89C81A51A87CCBF00AA00FF /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
C89C81A61A87CCBF00AA00FF /* Build configuration list for PBXNativeTarget "RxTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
C89C81A71A87CCBF00AA00FF /* Debug */,
|
||||
C89C81A81A87CCBF00AA00FF /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = C89C81841A87CCBF00AA00FF /* Project object */;
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges</key>
|
||||
<true/>
|
||||
<key>SnapshotAutomaticallyBeforeSignificantChanges</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0610"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C89C818C1A87CCBF00AA00FF"
|
||||
BuildableName = "Rx.framework"
|
||||
BlueprintName = "Rx"
|
||||
ReferencedContainer = "container:Rx.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C89C81971A87CCBF00AA00FF"
|
||||
BuildableName = "RxTests.xctest"
|
||||
BlueprintName = "RxTests"
|
||||
ReferencedContainer = "container:Rx.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
buildConfiguration = "Debug">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C89C81971A87CCBF00AA00FF"
|
||||
BuildableName = "RxTests.xctest"
|
||||
BlueprintName = "RxTests"
|
||||
ReferencedContainer = "container:Rx.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C89C818C1A87CCBF00AA00FF"
|
||||
BuildableName = "Rx.framework"
|
||||
BlueprintName = "Rx"
|
||||
ReferencedContainer = "container:Rx.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Debug"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
allowLocationSimulation = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C89C818C1A87CCBF00AA00FF"
|
||||
BuildableName = "Rx.framework"
|
||||
BlueprintName = "Rx"
|
||||
ReferencedContainer = "container:Rx.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
<AdditionalOption
|
||||
key = "DYLD_INSERT_LIBRARIES"
|
||||
value = "/usr/lib/libgmalloc.dylib"
|
||||
isEnabled = "YES">
|
||||
</AdditionalOption>
|
||||
<AdditionalOption
|
||||
key = "NSZombieEnabled"
|
||||
value = "YES"
|
||||
isEnabled = "YES">
|
||||
</AdditionalOption>
|
||||
<AdditionalOption
|
||||
key = "MallocGuardEdges"
|
||||
value = ""
|
||||
isEnabled = "YES">
|
||||
</AdditionalOption>
|
||||
<AdditionalOption
|
||||
key = "MallocScribble"
|
||||
value = ""
|
||||
isEnabled = "YES">
|
||||
</AdditionalOption>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Release"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C89C818C1A87CCBF00AA00FF"
|
||||
BuildableName = "Rx.framework"
|
||||
BlueprintName = "Rx"
|
||||
ReferencedContainer = "container:Rx.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>Rx.xcscheme</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>2</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>SuppressBuildableAutocreation</key>
|
||||
<dict>
|
||||
<key>C89C818C1A87CCBF00AA00FF</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>C89C81971A87CCBF00AA00FF</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// 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!) -> Result<T> {
|
||||
if let typedResult = result as? T {
|
||||
return success(typedResult)
|
||||
}
|
||||
else {
|
||||
return .Error(CastError)
|
||||
}
|
||||
}
|
||||
|
||||
public func makeOptionalResult<T>(result: T) -> Result<T?> {
|
||||
return success(result)
|
||||
}
|
||||
|
||||
public func makeOptional<T>(result: T) -> T? {
|
||||
return result
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
//
|
||||
// Cancelable.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/12/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol Cancelable : Disposable {
|
||||
var disposed: Bool { get }
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
//
|
||||
// AsyncLock.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/21/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class AsyncLock : Disposable {
|
||||
typealias Action = () -> Result<Void>
|
||||
|
||||
private var lock: Lock = Lock()
|
||||
|
||||
private var queue: Queue<Action> = Queue(capacity: 2)
|
||||
private var isAcquired: Bool = false
|
||||
private var hasFaulted: Bool = false
|
||||
|
||||
init() {
|
||||
|
||||
}
|
||||
|
||||
func wait(action: Action) -> Result<Void> {
|
||||
let isOwner = lock.calculateLocked { () -> Bool in
|
||||
if self.hasFaulted {
|
||||
return false
|
||||
}
|
||||
|
||||
self.queue.enqueue(action)
|
||||
let isOwner = !self.isAcquired
|
||||
self.isAcquired = true
|
||||
|
||||
return isOwner
|
||||
}
|
||||
|
||||
if !isOwner {
|
||||
return SuccessResult
|
||||
}
|
||||
|
||||
while true {
|
||||
let nextAction = lock.calculateLocked { () -> Action? in
|
||||
if self.queue.count > 0 {
|
||||
return self.queue.dequeue()
|
||||
}
|
||||
else {
|
||||
self.isAcquired = false
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if let nextAction = nextAction {
|
||||
let executeResult = nextAction() >>! { e in
|
||||
self.dispose()
|
||||
return .Error(e)
|
||||
}
|
||||
|
||||
if executeResult.error != nil {
|
||||
return executeResult
|
||||
}
|
||||
}
|
||||
else {
|
||||
return SuccessResult
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func dispose() {
|
||||
lock.performLocked { oldState in
|
||||
self.queue = Queue(capacity: 2)
|
||||
self.hasFaulted = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// Lock.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/31/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct Lock {
|
||||
private var _lock = OS_SPINLOCK_INIT
|
||||
|
||||
public init() {
|
||||
|
||||
}
|
||||
|
||||
public mutating func performLocked(@noescape action: () -> Void) {
|
||||
OSSpinLockLock(&_lock)
|
||||
action()
|
||||
OSSpinLockUnlock(&_lock)
|
||||
}
|
||||
|
||||
public mutating func calculateLocked<T>(@noescape action: () -> T) -> T {
|
||||
OSSpinLockLock(&_lock)
|
||||
let result = action()
|
||||
OSSpinLockUnlock(&_lock)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
//
|
||||
// Bag.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/28/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
private struct BagPrivate {
|
||||
static let maxElements = Bag<Void>.KeyType.max - 1 // this is guarding from theoretical endless loop
|
||||
}
|
||||
|
||||
public struct Bag<Element> {
|
||||
public typealias KeyType = Int
|
||||
|
||||
private var map: [KeyType: Element] = Dictionary(minimumCapacity: 5)
|
||||
private var nextKey = KeyType.min
|
||||
|
||||
public init() {
|
||||
}
|
||||
|
||||
public var count: Int {
|
||||
get {
|
||||
return map.count
|
||||
}
|
||||
}
|
||||
|
||||
public mutating func put(x: Element) -> KeyType {
|
||||
if map.count >= BagPrivate.maxElements {
|
||||
rxFatalError("Too many elements")
|
||||
}
|
||||
|
||||
while map[nextKey] != nil {
|
||||
nextKey++
|
||||
}
|
||||
|
||||
map[nextKey] = x
|
||||
|
||||
return nextKey
|
||||
}
|
||||
|
||||
public var all: [Element]
|
||||
{
|
||||
get {
|
||||
return self.map.values.array
|
||||
}
|
||||
}
|
||||
|
||||
public mutating func removeAll() {
|
||||
map.removeAll(keepCapacity: false)
|
||||
}
|
||||
|
||||
public mutating func removeKey(key: KeyType) -> Element? {
|
||||
return map.removeValueForKey(key)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
//
|
||||
// Queue.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/21/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct Queue<T> {
|
||||
let resizeFactor = 2
|
||||
|
||||
private var storage: [T?]
|
||||
private var _count: Int
|
||||
private var pushNextIndex: Int
|
||||
private var initialCapacity: Int
|
||||
|
||||
public init(capacity: Int) {
|
||||
initialCapacity = capacity
|
||||
|
||||
storage = []
|
||||
_count = 0
|
||||
pushNextIndex = 0
|
||||
|
||||
resizeTo(capacity)
|
||||
}
|
||||
|
||||
private var dequeueIndex: Int {
|
||||
get {
|
||||
var index = pushNextIndex - count
|
||||
return index < 0 ? index + self.storage.count : index
|
||||
}
|
||||
}
|
||||
|
||||
public var count: Int {
|
||||
get {
|
||||
return _count
|
||||
}
|
||||
}
|
||||
|
||||
public func peek() -> T {
|
||||
contract(count > 0)
|
||||
|
||||
return storage[dequeueIndex]!
|
||||
}
|
||||
|
||||
mutating private func resizeTo(size: Int) {
|
||||
var newStorage: [T?] = []
|
||||
newStorage.reserveCapacity(size)
|
||||
|
||||
var count = _count
|
||||
|
||||
for var i = 0; i < count; ++i {
|
||||
// does swift array have some more efficient methods of copying?
|
||||
newStorage.append(dequeue())
|
||||
}
|
||||
|
||||
while newStorage.count < size {
|
||||
newStorage.append(nil)
|
||||
}
|
||||
|
||||
_count = count
|
||||
pushNextIndex = count
|
||||
storage = newStorage
|
||||
}
|
||||
|
||||
public mutating func enqueue(item: T) {
|
||||
let queueFull = count == storage.count
|
||||
if count == storage.count {
|
||||
resizeTo(storage.count * resizeFactor)
|
||||
}
|
||||
|
||||
storage[pushNextIndex] = item
|
||||
pushNextIndex++
|
||||
_count = _count + 1
|
||||
|
||||
if pushNextIndex >= storage.count {
|
||||
pushNextIndex -= storage.count
|
||||
}
|
||||
}
|
||||
|
||||
public mutating func dequeue() -> T {
|
||||
contract(count > 0)
|
||||
|
||||
let index = dequeueIndex
|
||||
let value = storage[index]!
|
||||
|
||||
storage[index] = nil
|
||||
|
||||
_count = _count - 1
|
||||
|
||||
let downsizeLimit = storage.count / (resizeFactor * resizeFactor)
|
||||
if _count < downsizeLimit && downsizeLimit >= initialCapacity {
|
||||
resizeTo(storage.count / resizeFactor)
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// Disposable.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/8/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol Disposable
|
||||
{
|
||||
func dispose()
|
||||
}
|
||||
|
||||
public func allSucceedOrDispose(disposables: [Result<Disposable>]) -> Result<Disposable> {
|
||||
let errors = disposables.filter { d in d.error != nil }
|
||||
let numberOfFailures = errors.count
|
||||
if numberOfFailures == 0 {
|
||||
return success(CompositeDisposable(disposables: disposables.map { d in d.value!}))
|
||||
}
|
||||
else {
|
||||
// dispose all of the resources
|
||||
let diposeResult: [Void] = disposables.map { d in
|
||||
switch d {
|
||||
case .Success(let disposable):
|
||||
disposable.value.dispose()
|
||||
break;
|
||||
case .Error(let error): break
|
||||
}
|
||||
|
||||
return ()
|
||||
}
|
||||
return createCompositeFailure(errors)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// AnonymousDisposable.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/15/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class AnonymousDisposable : DisposeBase, Disposable {
|
||||
public typealias DisposeAction = () -> Void
|
||||
|
||||
var lock = Lock()
|
||||
var disposeAction: DisposeAction?
|
||||
|
||||
public init(_ disposeAction: DisposeAction) {
|
||||
self.disposeAction = disposeAction
|
||||
super.init()
|
||||
}
|
||||
|
||||
public func dispose() {
|
||||
let toDispose: DisposeAction? = lock.calculateLocked {
|
||||
var action = self.disposeAction
|
||||
self.disposeAction = nil
|
||||
return action
|
||||
}
|
||||
|
||||
if let toDispose = toDispose {
|
||||
toDispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
//
|
||||
// CompositeDisposable.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/20/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class CompositeDisposable : DisposeBase, Disposable {
|
||||
public typealias BagKey = Bag<Disposable>.KeyType
|
||||
|
||||
typealias State = (
|
||||
disposables: MutatingBox<Bag<Disposable>>!,
|
||||
disposed: Bool
|
||||
)
|
||||
|
||||
var lock: Lock = Lock()
|
||||
var state: State = (
|
||||
disposables: MutatingBox(Bag()),
|
||||
disposed: false
|
||||
)
|
||||
|
||||
public override init() {
|
||||
}
|
||||
|
||||
public init(_ disposable1: Disposable, _ disposable2: Disposable) {
|
||||
let bag = state.disposables
|
||||
|
||||
bag.value.put(disposable1)
|
||||
bag.value.put(disposable2)
|
||||
}
|
||||
|
||||
public init(_ disposable1: Disposable, _ disposable2: Disposable, _ disposable3: Disposable) {
|
||||
let bag = state.disposables
|
||||
|
||||
bag.value.put(disposable1)
|
||||
bag.value.put(disposable2)
|
||||
bag.value.put(disposable3)
|
||||
}
|
||||
|
||||
public init(disposables: [Disposable]) {
|
||||
let bag = state.disposables
|
||||
|
||||
for disposable in disposables {
|
||||
bag.value.put(disposable)
|
||||
}
|
||||
}
|
||||
|
||||
public func addDisposable(disposable: Disposable) -> BagKey? {
|
||||
// this should be let
|
||||
// bucause of compiler bug it's var
|
||||
let key = self.lock.calculateLocked { oldState -> BagKey? in
|
||||
if state.disposed {
|
||||
return nil
|
||||
}
|
||||
else {
|
||||
let key = state.disposables.value.put(disposable)
|
||||
return key
|
||||
}
|
||||
}
|
||||
|
||||
if key == nil {
|
||||
disposable.dispose()
|
||||
}
|
||||
|
||||
return key
|
||||
}
|
||||
|
||||
public var count: Int {
|
||||
get {
|
||||
return self.lock.calculateLocked {
|
||||
self.state.disposables.value.count
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func removeDisposable(disposeKey: BagKey) {
|
||||
let disposable = self.lock.calculateLocked { Void -> Disposable? in
|
||||
return state.disposables.value.removeKey(disposeKey)
|
||||
}
|
||||
|
||||
if let disposable = disposable {
|
||||
disposable.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
public func dispose() {
|
||||
let oldDisposables = self.lock.calculateLocked { Void -> [Disposable] in
|
||||
if state.disposed {
|
||||
return []
|
||||
}
|
||||
|
||||
let disposables = state.disposables
|
||||
var allValues = disposables.value.all
|
||||
|
||||
state.disposed = true
|
||||
state.disposables = nil
|
||||
|
||||
return allValues
|
||||
}
|
||||
|
||||
for d in oldDisposables {
|
||||
d.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
//
|
||||
// DefaultDisposable.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/15/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct DefaultDisposable : Disposable {
|
||||
|
||||
public init() {
|
||||
|
||||
}
|
||||
|
||||
public func dispose() {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
//
|
||||
// DisposeBag.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/25/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class DisposeBag: DisposeBase, Disposable {
|
||||
private var lock = Lock()
|
||||
|
||||
private var disposables: [Disposable] = []
|
||||
|
||||
public override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
public func addDisposable(disposable: Disposable) {
|
||||
disposables.append(disposable)
|
||||
}
|
||||
|
||||
public func addDisposable(disposable: Result<Disposable>) {
|
||||
disposables.append(*disposable)
|
||||
}
|
||||
|
||||
public func dispose() {
|
||||
let oldDisposables = lock.calculateLocked { () -> [Disposable] in
|
||||
var disposables = self.disposables
|
||||
self.disposables.removeAll(keepCapacity: true)
|
||||
|
||||
return disposables
|
||||
}
|
||||
|
||||
for disposable in oldDisposables {
|
||||
disposable.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
dispose()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// DisposeBase.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 4/4/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class DisposeBase {
|
||||
init() {
|
||||
#if DEBUG
|
||||
OSAtomicIncrement32(&resourceCount)
|
||||
#endif
|
||||
}
|
||||
|
||||
deinit {
|
||||
#if DEBUG
|
||||
OSAtomicDecrement32(&resourceCount)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
//
|
||||
// SerialDisposable.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/12/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class SerialDisposable : DisposeBase, Cancelable {
|
||||
typealias State = (
|
||||
current: Disposable?,
|
||||
disposed: Bool
|
||||
)
|
||||
|
||||
var lock = Lock()
|
||||
var state: State = (
|
||||
current: nil,
|
||||
disposed: false
|
||||
)
|
||||
|
||||
public var disposed: Bool {
|
||||
get {
|
||||
return state.disposed
|
||||
}
|
||||
}
|
||||
|
||||
override public init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
public func setDisposable(disposable: Disposable) {
|
||||
var disposable: Disposable? = self.lock.calculateLocked {
|
||||
if state.disposed {
|
||||
return disposable
|
||||
}
|
||||
else {
|
||||
var toDispose = state.current
|
||||
state.current = disposable
|
||||
return toDispose
|
||||
}
|
||||
}
|
||||
|
||||
if let disposable = disposable {
|
||||
disposable.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
public func dispose() {
|
||||
var disposable: Disposable? = self.lock.calculateLocked {
|
||||
if state.disposed {
|
||||
return nil
|
||||
}
|
||||
else {
|
||||
state.disposed = true
|
||||
return state.current
|
||||
}
|
||||
}
|
||||
|
||||
if let disposable = disposable {
|
||||
disposable.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
//
|
||||
// SingleAssignmentDisposable.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/15/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class SingleAssignmentDisposable : DisposeBase, Disposable {
|
||||
typealias State = (
|
||||
disposed: Bool,
|
||||
disposableSet: Bool,
|
||||
disposable: Disposable?
|
||||
)
|
||||
|
||||
var lock = Lock()
|
||||
var state: State = (
|
||||
disposed: false,
|
||||
disposableSet: false,
|
||||
disposable: nil
|
||||
)
|
||||
|
||||
public override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
public func setDisposable(newDisposable: Disposable) {
|
||||
var disposable: Disposable? = self.lock.calculateLocked { oldState in
|
||||
|
||||
if state.disposableSet {
|
||||
rxFatalError("oldState.disposable != nil")
|
||||
}
|
||||
|
||||
state.disposableSet = true
|
||||
|
||||
if state.disposed {
|
||||
return newDisposable
|
||||
}
|
||||
|
||||
state.disposable = newDisposable
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if let disposable = disposable {
|
||||
return disposable.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
public func dispose() {
|
||||
var disposable: Disposable? = lock.calculateLocked { old in
|
||||
state.disposed = true
|
||||
var dispose = state.disposable
|
||||
state.disposable = nil
|
||||
|
||||
return dispose
|
||||
}
|
||||
|
||||
if let disposable = disposable {
|
||||
disposable.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// Error.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/28/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
let RxErrorDomain = "RxErrorDomain"
|
||||
let RxCompositeFailures = "RxCompositeFailures"
|
||||
|
||||
public enum RxErrorCode : Int {
|
||||
case Unknown = 0
|
||||
case Composite = 1
|
||||
case Cast = 2
|
||||
case Disposed = 3
|
||||
}
|
||||
|
||||
// This defines error type for entire project.
|
||||
// It's not practical to have different error handling types for different areas of the app.
|
||||
// This is good enough solution for now unless proven otherwise
|
||||
public typealias ErrorType = NSError
|
||||
|
||||
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)
|
||||
|
||||
func createCompositeFailure<T>(failures: [Result<T>]) -> Result<T> {
|
||||
let description: [NSObject : AnyObject] = [ RxCompositeFailures : Box(failures.map { $0.error! }) ]
|
||||
let e = NSError(domain: RxErrorDomain, code: RxErrorCode.Composite.rawValue , userInfo: description)
|
||||
|
||||
return .Error(e)
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
//
|
||||
// Event.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/8/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
/// Due to current swift limitations, we have to include this Box in Result.
|
||||
/// Swift cannot handle an enum with multiple associated data (A, NSError) where one is of unknown size (A)
|
||||
/// This can be swiftified once the compiler is completed
|
||||
|
||||
/**
|
||||
* Represents event that happened
|
||||
* `Box` is there because of a bug in swift compiler
|
||||
* >> error: unimplemented IR generation feature non-fixed multi-payload enum layout
|
||||
*/
|
||||
public enum Event<Element> {
|
||||
// Box is used is because swift compiler doesn't know
|
||||
// how to handle `Next(Element)` and it crashes.
|
||||
case Next(Box<Element>) // next element of a sequence
|
||||
case Error(ErrorType) // sequence failed with error
|
||||
case Completed // sequence terminated successfully
|
||||
}
|
||||
|
||||
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)"
|
||||
}
|
||||
}
|
||||
|
||||
public func == <T: Equatable>(lhs: Event<T>, rhs: Event<T>) -> Bool {
|
||||
switch (lhs, rhs) {
|
||||
case (.Completed, .Completed): return true
|
||||
case (.Error(let e1), .Error(let e2)): return e1 == e2
|
||||
case (.Next(let v1), .Next(let v2)): return v1.value == v2.value
|
||||
default: return false
|
||||
}
|
||||
}
|
||||
|
||||
extension Event {
|
||||
public var isStopEvent: Bool {
|
||||
get {
|
||||
switch self {
|
||||
case .Next:
|
||||
return false
|
||||
case .Error: fallthrough
|
||||
case .Completed: return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var value: Element? {
|
||||
get {
|
||||
switch self {
|
||||
case .Next(let value):
|
||||
return value.value
|
||||
case .Error: fallthrough
|
||||
case .Completed: return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
//
|
||||
// Observable+Subscription.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/21/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension Observable {
|
||||
func subscribeSafe(observer: ObserverOf<Element>) -> Result<Disposable> {
|
||||
if let observableBase = self as? ObservableBase<Element> {
|
||||
return observableBase.subscribe(observer)
|
||||
}
|
||||
|
||||
var mutableObserver = observer
|
||||
|
||||
return self.subscribe(observer) >>! { error in
|
||||
return mutableObserver.on(Event<Element>.Error(error)) >>> { DefaultDisposable() }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public func subscribe<E>
|
||||
(on: (event: Event<E>) -> Void)
|
||||
(source: Observable<E>) -> Result<Disposable> {
|
||||
let observer: ObserverOf<E> = ObserverOf(AnonymousObserver { e in
|
||||
on(event: e)
|
||||
return SuccessResult
|
||||
})
|
||||
return source.subscribe(observer)
|
||||
}
|
||||
|
||||
public func subscribeNext<E>
|
||||
(onNext: (element: E) -> Void)
|
||||
(source: Observable<E>) -> Result<Disposable> {
|
||||
let observer: ObserverOf<E> = ObserverOf(AnonymousObserver { e in
|
||||
switch e {
|
||||
case .Next(let e):
|
||||
onNext(element: e.value)
|
||||
default:
|
||||
break
|
||||
}
|
||||
return SuccessResult
|
||||
})
|
||||
return source.subscribe(observer)
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// Observable.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/8/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
* Using protocol for Observer complicates implementation too much
|
||||
*/
|
||||
public class Observable<Element> {
|
||||
typealias ObserverAdapter = SinkOf<Event<Element>>
|
||||
|
||||
public init() {
|
||||
#if DEBUG
|
||||
OSAtomicIncrement32(&resourceCount)
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Subscribes `observer` to receive events from this observable
|
||||
public func subscribe(observer: ObserverOf<Element>) -> Result<Disposable> {
|
||||
return abstractMethod()
|
||||
}
|
||||
|
||||
deinit {
|
||||
#if DEBUG
|
||||
OSAtomicDecrement32(&resourceCount)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
//
|
||||
// Aggregate.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 4/1/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class Aggregate_<SourceType, AccumulateType, ResultType> : Sink<ResultType>, ObserverClassType {
|
||||
typealias Element = SourceType
|
||||
typealias ParentType = Aggregate<SourceType, AccumulateType, ResultType>
|
||||
|
||||
let parent: ParentType
|
||||
var accumulation: AccumulateType
|
||||
|
||||
init(parent: ParentType, observer: ObserverOf<ResultType>, cancel: Disposable) {
|
||||
self.parent = parent
|
||||
|
||||
self.accumulation = parent.seed
|
||||
|
||||
super.init(observer: observer, cancel: cancel)
|
||||
}
|
||||
|
||||
func on(event: Event<SourceType>) -> Result<Void> {
|
||||
switch event {
|
||||
case .Next(let boxedValue):
|
||||
let value = boxedValue.value
|
||||
return parent.accumulator(accumulation, value) >== { result in
|
||||
self.accumulation = result
|
||||
return SuccessResult
|
||||
} >>! { e in
|
||||
let result = self.observer.on(.Error(e))
|
||||
self.dispose()
|
||||
return result >>> { .Error(e) }
|
||||
}
|
||||
case .Error(let e):
|
||||
let result = self.observer.on(.Error(e))
|
||||
self.dispose()
|
||||
return result
|
||||
case .Completed:
|
||||
return self.parent.resultSelector(self.accumulation) >== { result in
|
||||
let result = self.observer.on(.Next(Box(result))) >>> {
|
||||
self.observer.on(.Completed)
|
||||
}
|
||||
self.dispose()
|
||||
return result
|
||||
} >>! { error in
|
||||
let result = self.observer.on(.Error(error))
|
||||
self.dispose()
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Aggregate<SourceType, AccumulateType, ResultType> : Producer<ResultType> {
|
||||
typealias AccumulatorType = (AccumulateType, SourceType) -> Result<AccumulateType>
|
||||
typealias ResultSelectorType = (AccumulateType) -> Result<ResultType>
|
||||
|
||||
let source: Observable<SourceType>
|
||||
let seed: AccumulateType
|
||||
let accumulator: AccumulatorType
|
||||
let resultSelector: ResultSelectorType
|
||||
|
||||
init(source: Observable<SourceType>, seed: AccumulateType, accumulator: AccumulatorType, resultSelector: ResultSelectorType) {
|
||||
self.source = source
|
||||
self.seed = seed
|
||||
self.accumulator = accumulator
|
||||
self.resultSelector = resultSelector
|
||||
}
|
||||
|
||||
override func run(observer: ObserverOf<ResultType>, cancel: Disposable, setSink: (Disposable) -> Void) -> Result<Disposable> {
|
||||
let sink = Aggregate_(parent: self, observer: observer, cancel: cancel)
|
||||
setSink(sink)
|
||||
return source.subscribeSafe(ObserverOf(sink))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// AnonymousObservable.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/8/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class AnonymousObservable<Element> : ObservableBase<Element> {
|
||||
typealias SubscribeHandler = (ObserverOf<Element>) -> Result<Disposable>
|
||||
|
||||
let subscribeHandler: SubscribeHandler
|
||||
|
||||
public init(_ subscribeHandler: SubscribeHandler) {
|
||||
self.subscribeHandler = subscribeHandler
|
||||
}
|
||||
|
||||
public override func subscribeCore(observer: ObserverOf<Element>) -> Result<Disposable> {
|
||||
return subscribeHandler(observer)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
//
|
||||
// AsObservable.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/27/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class AsObservableSink_<ElementType> : ObserverClassType, Disposable {
|
||||
typealias Element = ElementType
|
||||
|
||||
let sink: Sink<Element>
|
||||
|
||||
func dispose() {
|
||||
sink.dispose()
|
||||
}
|
||||
|
||||
func on(event: Event<Element>) -> Result<Void> {
|
||||
return self.sink.state.observer.on(event)
|
||||
}
|
||||
|
||||
init(observer: ObserverOf<Element>, cancel: Disposable) {
|
||||
self.sink = Sink(observer: observer, cancel: cancel)
|
||||
}
|
||||
}
|
||||
|
||||
class AsObservable<Element> : Producer<Element> {
|
||||
|
||||
let source: Observable<Element>
|
||||
|
||||
init(source: Observable<Element>) {
|
||||
self.source = source
|
||||
}
|
||||
|
||||
func omega() -> Observable<Element> {
|
||||
return self
|
||||
}
|
||||
|
||||
func eval() -> Observable<Element> {
|
||||
return source
|
||||
}
|
||||
|
||||
override func run(observer: ObserverOf<Element>, cancel: Disposable, setSink: (Disposable) -> Void) -> Result<Disposable> {
|
||||
let sink = AsObservableSink_(observer: observer, cancel: cancel)
|
||||
setSink(sink)
|
||||
return source.subscribeSafe(ObserverOf(sink))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,210 @@
|
|||
//
|
||||
// CombineLatest.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/21/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class First<Element1, Element2, ResultType>: ObserverClassType {
|
||||
typealias Parent = CombineLatest_<Element1, Element2, ResultType>
|
||||
typealias Element = Element1
|
||||
|
||||
let parent: Parent
|
||||
let disposeSelf: Disposable
|
||||
|
||||
var other: Second<Element1, Element2, ResultType>? = nil
|
||||
|
||||
// under parent lock
|
||||
var value: Element1? = nil
|
||||
var done: Bool = false
|
||||
|
||||
init(parent: Parent, disposeSelf: Disposable) {
|
||||
self.parent = parent
|
||||
self.disposeSelf = disposeSelf
|
||||
}
|
||||
|
||||
func on(event: Event<Element>) -> Result<Void> {
|
||||
return parent.lock.calculateLocked { _ in
|
||||
let (observer, disposable, disposed) = self.parent.state
|
||||
|
||||
switch event {
|
||||
case .Next(let boxedValue):
|
||||
let value = boxedValue.value
|
||||
self.value = value
|
||||
|
||||
if let otherValue = self.other?.value {
|
||||
let result: Result<ResultType> = self.parent.parent.selector(value, otherValue)
|
||||
|
||||
return (result >== { res in
|
||||
return observer.on(.Next(Box(res)))
|
||||
}) >>! { e -> Result<Void> in
|
||||
let resul = observer.on(.Error(e))
|
||||
self.parent.dispose()
|
||||
return result >>> { .Error(e) }
|
||||
}
|
||||
}
|
||||
else if self.other?.done ?? false {
|
||||
let result = observer.on(.Completed)
|
||||
self.parent.dispose()
|
||||
return result
|
||||
}
|
||||
else {
|
||||
return SuccessResult
|
||||
}
|
||||
case .Error(let error):
|
||||
let result = observer.on(.Error(error))
|
||||
self.parent.dispose()
|
||||
return result
|
||||
case .Completed:
|
||||
self.done = true
|
||||
if self.other?.done ?? false {
|
||||
let result = observer.on(.Completed)
|
||||
self.parent.dispose()
|
||||
return result
|
||||
}
|
||||
else {
|
||||
self.disposeSelf.dispose()
|
||||
return SuccessResult
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Second<Element1, Element2, ResultType>: ObserverClassType {
|
||||
typealias Parent = CombineLatest_<Element1, Element2, ResultType>
|
||||
typealias Element = Element2
|
||||
|
||||
let parent: Parent
|
||||
let disposeSelf: Disposable
|
||||
|
||||
var other: First<Element1, Element2, ResultType>? = nil
|
||||
|
||||
var value: Element2? = nil
|
||||
var done: Bool = false
|
||||
|
||||
init(parent: Parent, disposeSelf: Disposable) {
|
||||
self.parent = parent
|
||||
self.disposeSelf = disposeSelf
|
||||
self.other = nil
|
||||
}
|
||||
|
||||
func on(event: Event<Element>) -> Result<Void> {
|
||||
return parent.lock.calculateLocked { _ in
|
||||
let (observer, disposable, disposed) = self.parent.state
|
||||
|
||||
switch event {
|
||||
case .Next(let boxedValue):
|
||||
let value = boxedValue.value
|
||||
self.value = value
|
||||
|
||||
if let otherValue = self.other?.value {
|
||||
let result: Result<ResultType> = self.parent.parent.selector(otherValue, value)
|
||||
return (result >== { res in
|
||||
return observer.on(.Next(Box(res)))
|
||||
}) >>! { e -> Result<Void> in
|
||||
let result = observer.on(.Error(e))
|
||||
self.parent.dispose()
|
||||
return result >>> { .Error(e) }
|
||||
}
|
||||
}
|
||||
else if self.other?.done ?? false {
|
||||
let result = observer.on(.Completed)
|
||||
self.parent.dispose()
|
||||
return result
|
||||
}
|
||||
else {
|
||||
return SuccessResult
|
||||
}
|
||||
case .Error(let error):
|
||||
let result = observer.on(.Error(error))
|
||||
self.parent.dispose()
|
||||
return result
|
||||
case .Completed:
|
||||
self.done = true
|
||||
if self.other?.done ?? false {
|
||||
let result = observer.on(.Completed)
|
||||
self.parent.dispose()
|
||||
return result
|
||||
}
|
||||
else {
|
||||
self.disposeSelf.dispose()
|
||||
return SuccessResult
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class CombineLatest_<Element1, Element2, ResultType> : Sink<ResultType> {
|
||||
typealias Parent = CombineLatest<Element1, Element2, ResultType>
|
||||
|
||||
let parent: Parent
|
||||
|
||||
var lock = Lock()
|
||||
|
||||
init(parent: Parent, observer: ObserverOf<ResultType>, cancel: Disposable) {
|
||||
self.parent = parent
|
||||
|
||||
super.init(observer: observer, cancel: cancel)
|
||||
}
|
||||
|
||||
func run() -> Result<Disposable> {
|
||||
let snapshot = self.state
|
||||
|
||||
let subscription1 = SingleAssignmentDisposable()
|
||||
let subscription2 = SingleAssignmentDisposable()
|
||||
|
||||
let sink1 = First(parent: self, disposeSelf: subscription1)
|
||||
let sink2 = Second(parent: self, disposeSelf: subscription2)
|
||||
|
||||
sink1.other = sink2
|
||||
sink2.other = sink1
|
||||
|
||||
let removeBond = AnonymousDisposable {
|
||||
sink1.other = nil
|
||||
sink2.other = nil
|
||||
}
|
||||
|
||||
return doAll([
|
||||
parent.observable1.subscribeSafe(ObserverOf(sink1)) >== { disposable in
|
||||
subscription1.setDisposable(disposable)
|
||||
},
|
||||
parent.observable2.subscribeSafe(ObserverOf(sink2)) >== { disposable in
|
||||
subscription2.setDisposable(disposable)
|
||||
}
|
||||
]) >>> {
|
||||
return success(CompositeDisposable(subscription1, subscription2, removeBond))
|
||||
} >>! { e in
|
||||
subscription1.dispose()
|
||||
subscription2.dispose()
|
||||
removeBond.dispose()
|
||||
return .Error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CombineLatest<Element1, Element2, ResultType> : Producer<ResultType> {
|
||||
typealias SelectorType = (Element1, Element2) -> Result<ResultType>
|
||||
|
||||
let observable1: Observable<Element1>
|
||||
let observable2: Observable<Element2>
|
||||
let selector: SelectorType
|
||||
|
||||
init(observable1: Observable<Element1>, observable2: Observable<Element2>, selector: SelectorType) {
|
||||
self.observable1 = observable1
|
||||
self.observable2 = observable2
|
||||
|
||||
self.selector = selector
|
||||
}
|
||||
|
||||
override func run(observer: ObserverOf<ResultType>, cancel: Disposable, setSink: (Disposable) -> Void) -> Result<Disposable> {
|
||||
let sink = CombineLatest_(parent: self, observer: observer, cancel: cancel)
|
||||
setSink(sink)
|
||||
return sink.run()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// Concat.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/21/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class Concat_<Element> : ConcatSink<Element> {
|
||||
override init(observer: ObserverOf<Element>, cancel: Disposable) {
|
||||
super.init(observer: observer, cancel: cancel)
|
||||
}
|
||||
|
||||
override func on(event: Event<Element>) -> Result<Void> {
|
||||
switch event {
|
||||
case .Next(let next):
|
||||
return observer.on(event)
|
||||
case .Error:
|
||||
let result = observer.on(event)
|
||||
dispose()
|
||||
return result
|
||||
case .Completed:
|
||||
return super.on(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Concat<Element> : Producer<Element> {
|
||||
let sources: [Observable<Element>]
|
||||
|
||||
init(sources: [Observable<Element>]) {
|
||||
self.sources = sources
|
||||
}
|
||||
|
||||
override func run(observer: ObserverOf<Element>, cancel: Disposable, setSink: (Disposable) -> Void) -> Result<Disposable> {
|
||||
let sink = Concat_(observer: observer, cancel: cancel)
|
||||
setSink(sink)
|
||||
|
||||
return sink.run(sources)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// ConcatSink.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/21/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class ConcatSink<Element> : TailRecursiveSink<Element> {
|
||||
override init(observer: ObserverOf<Element>, cancel: Disposable) {
|
||||
super.init(observer: observer, cancel: cancel)
|
||||
}
|
||||
|
||||
override func on(event: Event<Element>) -> Result<Void> {
|
||||
switch event {
|
||||
case .Completed:
|
||||
return scheduleMoveNext()
|
||||
default:
|
||||
return super.on(event)
|
||||
}
|
||||
}
|
||||
|
||||
override func extract(observable: Observable<Element>) -> [Observable<Element>]? {
|
||||
if let source = observable as? Concat<Element> {
|
||||
return source.sources
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
//
|
||||
// ConnectableObservable.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/1/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class Connection<SourceType, ResultType> : Disposable {
|
||||
typealias SelfType = Connection<SourceType, ResultType>
|
||||
|
||||
var parent: ConnectableObservable<SourceType, ResultType>?
|
||||
var subscription: Disposable?
|
||||
|
||||
init(parent: ConnectableObservable<SourceType, ResultType>, subscription: Disposable) {
|
||||
self.parent = parent
|
||||
self.subscription = subscription
|
||||
}
|
||||
|
||||
func dispose() {
|
||||
if let parent = parent {
|
||||
parent.lock.performLocked {
|
||||
subscription!.dispose()
|
||||
subscription = nil
|
||||
self.parent = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ConnectableObservable<SourceType, ResultType> : ConnectableObservableType<ResultType> {
|
||||
typealias ConnectionType = Connection<SourceType, ResultType>
|
||||
|
||||
let subject: SubjectType<SourceType, ResultType>
|
||||
let source: Observable<SourceType>
|
||||
|
||||
var lock = Lock()
|
||||
var connection: ConnectionType?
|
||||
|
||||
init(source: Observable<SourceType>, subject: SubjectType<SourceType, ResultType>) {
|
||||
self.source = asObservable(source)
|
||||
self.subject = subject
|
||||
self.connection = nil
|
||||
}
|
||||
|
||||
override func connect() -> Result<Disposable> {
|
||||
return self.lock.calculateLocked { oldConnection in
|
||||
if let connection = connection {
|
||||
return success(connection)
|
||||
}
|
||||
else {
|
||||
return self.source.subscribeSafe(ObserverOf(self.subject)) >== { disposable in
|
||||
self.connection = Connection(parent: self, subscription: disposable)
|
||||
return success(self.connection!)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func subscribe(observer: ObserverOf<ResultType>) -> Result<Disposable> {
|
||||
return subject.subscribeSafe(observer)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
//
|
||||
// DistinctUntilChanged.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/15/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class DistinctUntilChanged_<ElementType, Key>: Sink<ElementType>, ObserverClassType {
|
||||
typealias Element = ElementType
|
||||
|
||||
let parent: DistinctUntilChanged<ElementType, Key>
|
||||
var currentKey: Key? = nil
|
||||
|
||||
init(parent: DistinctUntilChanged<ElementType, Key>, observer: ObserverOf<ElementType>, cancel: Disposable) {
|
||||
self.parent = parent
|
||||
super.init(observer: observer, cancel: cancel)
|
||||
}
|
||||
|
||||
func on(event: Event<Element>) -> Result<Void> {
|
||||
let observer = super.state.observer
|
||||
|
||||
switch event {
|
||||
case .Next(let value):
|
||||
let keyResult = self.parent.selector(value.value)
|
||||
|
||||
let areEqualResult = keyResult >== { key -> Result<Bool> in
|
||||
if let currentKey = self.currentKey {
|
||||
return self.parent.comparer(currentKey, key)
|
||||
}
|
||||
else {
|
||||
return success(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (areEqualResult >== { areEqual in
|
||||
if areEqual {
|
||||
return SuccessResult
|
||||
}
|
||||
|
||||
self.currentKey = *keyResult
|
||||
|
||||
return observer.on(event)
|
||||
}) >>! { error in
|
||||
let result = observer.on(.Error(error))
|
||||
self.dispose()
|
||||
return result
|
||||
}
|
||||
case .Error: fallthrough
|
||||
case .Completed:
|
||||
let result = observer.on(event)
|
||||
self.dispose()
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DistinctUntilChanged<Element, Key>: Producer<Element> {
|
||||
typealias KeySelector = (Element) -> Result<Key>
|
||||
typealias EqualityComparer = (Key, Key) -> Result<Bool>
|
||||
|
||||
let source: Observable<Element>
|
||||
let selector: KeySelector
|
||||
let comparer: EqualityComparer
|
||||
|
||||
init(source: Observable<Element>, selector: KeySelector, comparer: EqualityComparer) {
|
||||
self.source = source
|
||||
self.selector = selector
|
||||
self.comparer = comparer
|
||||
}
|
||||
|
||||
override func run(observer: ObserverOf<Element>, cancel: Disposable, setSink: (Disposable) -> Void) -> Result<Disposable> {
|
||||
let sink = DistinctUntilChanged_(parent: self, observer: observer, cancel: cancel)
|
||||
setSink(sink)
|
||||
return source.subscribeSafe(ObserverOf(sink))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// Do.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/21/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class Do_<ElementType> : Sink<ElementType>, ObserverClassType, Disposable {
|
||||
typealias Element = ElementType
|
||||
typealias DoType = Do<Element>
|
||||
|
||||
let parent: DoType
|
||||
|
||||
init(parent: DoType, observer: ObserverOf<Element>, cancel: Disposable) {
|
||||
self.parent = parent
|
||||
super.init(observer: observer, cancel: cancel)
|
||||
}
|
||||
|
||||
func on(event: Event<Element>) -> Result<Void> {
|
||||
return (parent.eventHandler(event) >>! { error in
|
||||
// catch clause
|
||||
return self.state.observer.on(Event.Error(error)) >>> { self.dispose() }
|
||||
}) >== { _ in
|
||||
return self.state.observer.on(event) >>> {
|
||||
if event.isStopEvent {
|
||||
self.dispose()
|
||||
}
|
||||
return SuccessResult
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Do<Element> : Producer<Element> {
|
||||
typealias EventHandler = Event<Element> -> Result<Void>
|
||||
|
||||
let source: Observable<Element>
|
||||
let eventHandler: EventHandler
|
||||
|
||||
init(source: Observable<Element>, eventHandler: EventHandler) {
|
||||
self.source = source
|
||||
self.eventHandler = eventHandler
|
||||
}
|
||||
|
||||
override func run(observer: ObserverOf<Element>, cancel: Disposable, setSink: (Disposable) -> Void) -> Result<Disposable> {
|
||||
let sink = Do_(parent: self, observer: observer, cancel: cancel)
|
||||
|
||||
setSink(sink)
|
||||
|
||||
return self.source.subscribeSafe(ObserverOf(sink))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,315 @@
|
|||
//
|
||||
// Merge.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/28/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
// sequential
|
||||
|
||||
class Merge_Iter<ElementType> : ObserverClassType {
|
||||
typealias Element = ElementType
|
||||
typealias DisposeKey = Bag<Disposable>.KeyType
|
||||
|
||||
let parent: Merge_<ElementType>
|
||||
let disposeKey: DisposeKey
|
||||
|
||||
init(parent: Merge_<ElementType>, disposeKey: DisposeKey) {
|
||||
self.parent = parent
|
||||
self.disposeKey = disposeKey
|
||||
}
|
||||
|
||||
func on(event: Event<Element>) -> Result<Void> {
|
||||
switch event {
|
||||
case .Next:
|
||||
return parent.lock.calculateLocked {
|
||||
return self.parent.observer.on(event)
|
||||
}
|
||||
case .Error:
|
||||
return parent.lock.calculateLocked {
|
||||
self.parent.dispose()
|
||||
|
||||
return self.parent.observer.on(event)
|
||||
}
|
||||
case .Completed:
|
||||
let group = parent.mergeState.group
|
||||
group.removeDisposable(disposeKey)
|
||||
return parent.lock.calculateLocked {
|
||||
let state = parent.mergeState
|
||||
if state.stopped && state.group.count == 1 {
|
||||
let result = self.parent.observer.on(.Completed)
|
||||
self.parent.dispose()
|
||||
return result
|
||||
}
|
||||
return SuccessResult
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Merge_<ElementType> : Sink<ElementType>, ObserverClassType {
|
||||
typealias Element = Observable<ElementType>
|
||||
typealias MergeState = (stopped: Bool, group: CompositeDisposable, sourceSubscription: SingleAssignmentDisposable)
|
||||
|
||||
let parent: Merge<ElementType>
|
||||
|
||||
var lock = Lock()
|
||||
var mergeState: MergeState = (
|
||||
stopped: false,
|
||||
group: CompositeDisposable(),
|
||||
sourceSubscription: SingleAssignmentDisposable()
|
||||
)
|
||||
|
||||
init(parent: Merge<ElementType>, observer: ObserverOf<ElementType>, cancel: Disposable) {
|
||||
self.parent = parent
|
||||
|
||||
let state = self.mergeState
|
||||
|
||||
state.group.addDisposable(state.sourceSubscription)
|
||||
super.init(observer: observer, cancel: cancel)
|
||||
}
|
||||
|
||||
func run() -> Result<Disposable> {
|
||||
let state = self.mergeState
|
||||
|
||||
state.group.addDisposable(state.sourceSubscription)
|
||||
|
||||
return self.parent.sources.subscribe(ObserverOf(self)) >== { disposable in
|
||||
state.sourceSubscription.setDisposable(disposable)
|
||||
return success(state.group)
|
||||
}
|
||||
}
|
||||
|
||||
func on(event: Event<Observable<ElementType>>) -> Result<Void> {
|
||||
switch event {
|
||||
case .Next(let boxedValue):
|
||||
let value = boxedValue.value
|
||||
|
||||
let innerSubscription = SingleAssignmentDisposable()
|
||||
let mergeStateSnapshot = mergeState
|
||||
let maybeKey = mergeStateSnapshot.group.addDisposable(innerSubscription)
|
||||
|
||||
if let key = maybeKey {
|
||||
let observer = ObserverOf(Merge_Iter(parent: self, disposeKey: key))
|
||||
return value.subscribeSafe(observer) >== { disposable in
|
||||
innerSubscription.setDisposable(disposable)
|
||||
return SuccessResult
|
||||
}
|
||||
}
|
||||
// it was already disposed
|
||||
else {
|
||||
return SuccessResult
|
||||
}
|
||||
case .Error(let error):
|
||||
return lock.calculateLocked { Void -> Result<Void> in
|
||||
let result = self.observer.on(.Error(error))
|
||||
self.dispose()
|
||||
return result
|
||||
}
|
||||
case .Completed:
|
||||
return lock.calculateLocked {
|
||||
let mergeState = self.mergeState
|
||||
|
||||
let group = mergeState.group
|
||||
|
||||
self.mergeState.stopped = true
|
||||
|
||||
if group.count == 1 {
|
||||
let result = self.observer.on(.Completed)
|
||||
self.dispose()
|
||||
return result
|
||||
}
|
||||
else {
|
||||
mergeState.sourceSubscription.dispose()
|
||||
return SuccessResult
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// concurrent
|
||||
|
||||
class Merge_ConcurrentIter<ElementType> : ObserverClassType {
|
||||
typealias Element = ElementType
|
||||
typealias DisposeKey = Bag<Disposable>.KeyType
|
||||
|
||||
let parent: Merge_Concurrent<ElementType>
|
||||
let disposeKey: DisposeKey
|
||||
|
||||
init(parent: Merge_Concurrent<ElementType>, disposeKey: DisposeKey) {
|
||||
self.parent = parent
|
||||
self.disposeKey = disposeKey
|
||||
}
|
||||
|
||||
func on(event: Event<Element>) -> Result<Void> {
|
||||
switch event {
|
||||
case .Next:
|
||||
return parent.lock.calculateLocked {
|
||||
return self.parent.observer.on(event)
|
||||
}
|
||||
case .Error:
|
||||
return parent.lock.calculateLocked {
|
||||
let result = self.parent.observer.on(event)
|
||||
self.parent.dispose()
|
||||
return result
|
||||
}
|
||||
case .Completed:
|
||||
let mergeState = parent.mergeState
|
||||
mergeState.group.removeDisposable(disposeKey)
|
||||
return parent.lock.calculateLocked {
|
||||
if mergeState.queue.value.count > 0 {
|
||||
let s = mergeState.queue.value.dequeue()
|
||||
return self.parent.subscribe(s, group: mergeState.group)
|
||||
}
|
||||
else {
|
||||
parent.mergeState.activeCount = mergeState.activeCount - 1
|
||||
|
||||
var result = SuccessResult
|
||||
if mergeState.stopped && mergeState.activeCount == 0 {
|
||||
result = self.parent.observer.on(.Completed)
|
||||
self.parent.dispose()
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Merge_Concurrent<ElementType> : Sink<ElementType>, ObserverClassType {
|
||||
typealias Element = Observable<ElementType>
|
||||
typealias QueueType = Queue<Observable<ElementType>>
|
||||
|
||||
typealias MergeState = (
|
||||
stopped: Bool,
|
||||
queue: MutatingBox<QueueType>,
|
||||
sourceSubscription: SingleAssignmentDisposable,
|
||||
group: CompositeDisposable,
|
||||
activeCount: Int
|
||||
)
|
||||
|
||||
let parent: Merge<ElementType>
|
||||
|
||||
var lock = Lock()
|
||||
var mergeState: MergeState = (
|
||||
stopped: false,
|
||||
queue: MutatingBox(Queue(capacity: 2)),
|
||||
sourceSubscription: SingleAssignmentDisposable(),
|
||||
group: CompositeDisposable(),
|
||||
activeCount: 0
|
||||
)
|
||||
|
||||
init(parent: Merge<ElementType>, observer: ObserverOf<ElementType>, cancel: Disposable) {
|
||||
self.parent = parent
|
||||
|
||||
let state = self.mergeState
|
||||
|
||||
_ = state.group.addDisposable(state.sourceSubscription)
|
||||
super.init(observer: observer, cancel: cancel)
|
||||
}
|
||||
|
||||
func run() -> Result<Disposable> {
|
||||
let state = self.mergeState
|
||||
|
||||
state.group.addDisposable(state.sourceSubscription)
|
||||
|
||||
return self.parent.sources.subscribe(ObserverOf(self)) >== { disposable in
|
||||
state.sourceSubscription.setDisposable(disposable)
|
||||
return success(state.group)
|
||||
}
|
||||
}
|
||||
|
||||
func subscribe(innerSource: Observable<ElementType>, group: CompositeDisposable) -> Result<Void> {
|
||||
let subscription = SingleAssignmentDisposable()
|
||||
|
||||
let key = group.addDisposable(subscription)
|
||||
|
||||
if let key = key {
|
||||
let observer = ObserverOf(Merge_ConcurrentIter(parent: self, disposeKey: key))
|
||||
|
||||
return innerSource.subscribeSafe(observer) >== { disposable in
|
||||
subscription.setDisposable(disposable)
|
||||
return SuccessResult
|
||||
}
|
||||
}
|
||||
else {
|
||||
return SuccessResult
|
||||
}
|
||||
}
|
||||
|
||||
func on(event: Event<Observable<ElementType>>) -> Result<Void> {
|
||||
switch event {
|
||||
case .Next(let boxedValue):
|
||||
let value = boxedValue.value
|
||||
|
||||
return lock.calculateLocked {
|
||||
let mergeState = self.mergeState
|
||||
if mergeState.activeCount < self.parent.maxConcurrent {
|
||||
return self.subscribe(value, group: mergeState.group) >>> {
|
||||
self.mergeState.activeCount += 1
|
||||
return SuccessResult
|
||||
}
|
||||
}
|
||||
else {
|
||||
mergeState.queue.value.enqueue(value)
|
||||
return SuccessResult
|
||||
}
|
||||
}
|
||||
case .Error(let error):
|
||||
return lock.calculateLocked { Void -> Result<Void> in
|
||||
let result = self.observer.on(.Error(error))
|
||||
self.dispose()
|
||||
return result
|
||||
}
|
||||
case .Completed:
|
||||
return lock.calculateLocked {
|
||||
let mergeState = self.mergeState
|
||||
let group = mergeState.group
|
||||
|
||||
var result: Result<Void>
|
||||
|
||||
if mergeState.activeCount == 0 {
|
||||
result = self.observer.on(.Completed)
|
||||
self.dispose()
|
||||
}
|
||||
else {
|
||||
mergeState.sourceSubscription.dispose()
|
||||
result = SuccessResult
|
||||
}
|
||||
|
||||
return result >>> {
|
||||
self.mergeState.stopped = true
|
||||
return SuccessResult
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Merge<Element> : Producer<Element> {
|
||||
let sources: Observable<Observable<Element>>
|
||||
let maxConcurrent: Int
|
||||
|
||||
init(sources: Observable<Observable<Element>>, maxConcurrent: Int) {
|
||||
self.sources = sources
|
||||
self.maxConcurrent = maxConcurrent
|
||||
}
|
||||
|
||||
override func run(observer: ObserverOf<Element>, cancel: Disposable, setSink: (Disposable) -> Void) -> Result<Disposable> {
|
||||
if maxConcurrent > 0 {
|
||||
let sink = Merge_Concurrent(parent: self, observer: observer, cancel: cancel)
|
||||
setSink(sink)
|
||||
return sink.run()
|
||||
}
|
||||
else {
|
||||
let sink = Merge_(parent: self, observer: observer, cancel: cancel)
|
||||
setSink(sink)
|
||||
return sink.run()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
//
|
||||
// Multicast.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/27/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class Multicast_<SourceType, IntermediateType, ResultType>: Sink<ResultType>, ObserverClassType {
|
||||
typealias Element = ResultType
|
||||
typealias MutlicastType = Multicast<SourceType, IntermediateType, ResultType>
|
||||
|
||||
typealias IntermediateObservable = ConnectableObservableType<IntermediateType>
|
||||
typealias ResultObservable = Observable<ResultType>
|
||||
|
||||
let parent: MutlicastType
|
||||
|
||||
init(parent: MutlicastType, observer: ObserverOf<ResultType>, cancel: Disposable) {
|
||||
self.parent = parent
|
||||
super.init(observer: observer, cancel: cancel)
|
||||
}
|
||||
|
||||
func run() -> Result<Disposable> {
|
||||
let connectableResult: Result<IntermediateObservable> = parent.subjectSelector() >== { subject in
|
||||
return success(ConnectableObservable(source: self.parent.source, subject: subject))
|
||||
}
|
||||
|
||||
let observableResult: Result<ResultObservable> = connectableResult >== { connectable in
|
||||
return self.parent.selector(connectable)
|
||||
}
|
||||
|
||||
let subscribeResult: Result<Disposable> = observableResult >== { observable in
|
||||
let observerOf = ObserverOf(self)
|
||||
return observable.subscribeSafe(observerOf)
|
||||
}
|
||||
|
||||
let connectResult: Result<Disposable> = connectableResult >== { connectable in
|
||||
return connectable.connect()
|
||||
}
|
||||
|
||||
let compositeResult = allSucceedOrDispose([subscribeResult, connectResult])
|
||||
|
||||
return compositeResult >>! { e in
|
||||
return self.state.observer.on(Event.Error(e)) >>> { .Error(e) }
|
||||
}
|
||||
}
|
||||
|
||||
func on(event: Event<ResultType>) -> Result<Void> {
|
||||
let result = self.state.observer.on(event)
|
||||
switch event {
|
||||
case .Next: break
|
||||
case .Error: fallthrough
|
||||
case .Completed: self.dispose()
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
class Multicast<SourceType, IntermediateType, ResultType>: Producer<ResultType> {
|
||||
typealias SubjectSelectorType = () -> Result<SubjectType<SourceType, IntermediateType>>
|
||||
typealias SelectorType = (Observable<IntermediateType>) -> Result<Observable<ResultType>>
|
||||
|
||||
let source: Observable<SourceType>
|
||||
let subjectSelector: SubjectSelectorType
|
||||
let selector: SelectorType
|
||||
|
||||
init(source: Observable<SourceType>, subjectSelector: SubjectSelectorType, selector: SelectorType) {
|
||||
self.source = source
|
||||
self.subjectSelector = subjectSelector
|
||||
self.selector = selector
|
||||
}
|
||||
|
||||
override func run(observer: ObserverOf<ResultType>, cancel: Disposable, setSink: (Disposable) -> Void) -> Result<Disposable> {
|
||||
var sink = Multicast_(parent: self, observer: observer, cancel: cancel)
|
||||
setSink(sink)
|
||||
return sink.run()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// ObservableBase.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/15/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class ObservableBase<Element> : Observable<Element> {
|
||||
|
||||
override public func subscribe(observer: ObserverOf<Element>) -> Result<Disposable> {
|
||||
let autoDetachObserver = AutoDetachObserver(observer: observer)
|
||||
|
||||
return subscribeCore(ObserverOf(autoDetachObserver)) >== { disposable in
|
||||
autoDetachObserver.setDisposable(disposable)
|
||||
return success(disposable)
|
||||
}
|
||||
}
|
||||
|
||||
func subscribeCore(observer: ObserverOf<Element>) -> Result<Disposable> {
|
||||
return abstractMethod()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
//
|
||||
// ObserveSingleOn.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/15/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
// 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<ElementType> : ObserverClassType, Disposable {
|
||||
typealias Element = ElementType
|
||||
typealias Parent = ObserveSingleOn<ElementType>
|
||||
typealias State = (
|
||||
observer: ObserverOf<ElementType>,
|
||||
cancel: Disposable,
|
||||
disposed: Bool,
|
||||
element: Event<ElementType>?
|
||||
)
|
||||
|
||||
let parent: Parent
|
||||
|
||||
var lock = Lock()
|
||||
var state: State
|
||||
|
||||
init(parent: Parent, observer: ObserverOf<ElementType>, cancel: Disposable) {
|
||||
self.parent = parent
|
||||
self.state = (
|
||||
observer: observer,
|
||||
cancel: cancel,
|
||||
disposed: false,
|
||||
element: nil
|
||||
)
|
||||
}
|
||||
|
||||
func on(event: Event<Element>) -> Result<Void> {
|
||||
var elementToForward: Event<Element>?
|
||||
var stopEventToForward: Event<Element>?
|
||||
var observer: ObserverOf<Element>?
|
||||
|
||||
self.lock.performLocked {
|
||||
let scheduler = self.parent.scheduler
|
||||
|
||||
switch event {
|
||||
case .Next:
|
||||
if self.state.element != nil {
|
||||
rxFatalError("Sequence contains more then one element")
|
||||
}
|
||||
|
||||
self.state.element = event
|
||||
case .Error:
|
||||
if self.state.element != nil {
|
||||
rxFatalError("Observed sequence was expected to have more then one element")
|
||||
}
|
||||
stopEventToForward = event
|
||||
observer = self.state.observer
|
||||
case .Completed:
|
||||
elementToForward = self.state.element
|
||||
stopEventToForward = event
|
||||
observer = self.state.observer
|
||||
}
|
||||
}
|
||||
|
||||
if let stopEventToForward = stopEventToForward {
|
||||
self.parent.scheduler.schedule(()) { (_) in
|
||||
var r = SuccessResult
|
||||
if let elementToForward = elementToForward {
|
||||
r = observer!.on(elementToForward)
|
||||
}
|
||||
|
||||
r = r >>! { error in
|
||||
observer!.on(.Error(error))
|
||||
}
|
||||
|
||||
r = r >>> { observer!.on(stopEventToForward) }
|
||||
|
||||
self.dispose()
|
||||
|
||||
return r
|
||||
}
|
||||
}
|
||||
|
||||
return SuccessResult
|
||||
}
|
||||
|
||||
func dispose() {
|
||||
if state.disposed {
|
||||
return
|
||||
}
|
||||
|
||||
var cancel: Disposable? = self.lock.calculateLocked {
|
||||
if self.state.disposed {
|
||||
return nil
|
||||
}
|
||||
|
||||
var cancel = self.state.cancel
|
||||
|
||||
self.state.disposed = true
|
||||
self.state.cancel = DefaultDisposable()
|
||||
self.state.observer = ObserverOf(NopObserver())
|
||||
|
||||
return cancel
|
||||
}
|
||||
|
||||
if let cancel = cancel {
|
||||
cancel.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
func run() -> Result<Disposable> {
|
||||
return self.parent.source.subscribeSafe(ObserverOf(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(observer: ObserverOf<Element>, cancel: Disposable, setSink: (Disposable) -> Void) -> Result<Disposable> {
|
||||
let sink = ObserveSingleOnObserver(parent: self, observer: observer, cancel: cancel)
|
||||
setSink(sink)
|
||||
return sink.run()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
//
|
||||
// Producer.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/20/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct State<T> {
|
||||
var observer: ObserverOf<T>
|
||||
let sink: SingleAssignmentDisposable
|
||||
let subscription: SingleAssignmentDisposable
|
||||
|
||||
init(observer: ObserverOf<T>, sink: SingleAssignmentDisposable, subscription: SingleAssignmentDisposable) {
|
||||
self.observer = observer
|
||||
self.sink = sink
|
||||
self.subscription = subscription
|
||||
}
|
||||
|
||||
func assign(disposable: Disposable) {
|
||||
sink.setDisposable(disposable)
|
||||
}
|
||||
}
|
||||
|
||||
class Producer<Element> : Observable<Element> {
|
||||
|
||||
override func subscribe(observer: ObserverOf<Element>) -> Result<Disposable> {
|
||||
return subscribeRaw(observer, enableSafeguard: true)
|
||||
}
|
||||
|
||||
func subscribeRaw(observer: ObserverOf<Element>, enableSafeguard: Bool) -> Result<Disposable> {
|
||||
var state = State(observer: observer, sink: SingleAssignmentDisposable(), subscription: SingleAssignmentDisposable())
|
||||
|
||||
let d = CompositeDisposable(state.sink, state.subscription)
|
||||
|
||||
if enableSafeguard {
|
||||
state.observer = SafeObserver.create(observer, disposable: d)
|
||||
}
|
||||
|
||||
// TODO
|
||||
/*
|
||||
if (CurrentThreadScheduler.IsScheduleRequired)
|
||||
{
|
||||
CurrentThreadScheduler.Instance.Schedule(state, Run);
|
||||
}
|
||||
*/
|
||||
|
||||
let setSink: (Disposable) -> Void = { d in state.assign(d) }
|
||||
let runResult = run(state.observer, cancel: state.subscription, setSink: setSink)
|
||||
|
||||
return (runResult >== { disposable in
|
||||
state.subscription.setDisposable(disposable)
|
||||
return success(d)
|
||||
}) >>! { e -> Result<Disposable> in
|
||||
d.dispose()
|
||||
return .Error(e)
|
||||
}
|
||||
}
|
||||
|
||||
func run(observer: ObserverOf<Element>, cancel: Disposable, setSink: (Disposable) -> Void) -> Result<Disposable> {
|
||||
return abstractMethod()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
//
|
||||
// RefCount.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/5/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class RefCount_<Element> : Sink<Element>, ObserverClassType {
|
||||
let parent: RefCount<Element>
|
||||
typealias ParentState = RefCount<Element>.State
|
||||
|
||||
init(parent: RefCount<Element>, observer: ObserverOf<Element>, cancel: Disposable) {
|
||||
self.parent = parent
|
||||
super.init(observer: observer, cancel: cancel)
|
||||
}
|
||||
|
||||
func run() -> Result<Disposable> {
|
||||
let subscriptionResult: Result<Disposable> = self.parent.source.subscribeSafe(ObserverOf(self))
|
||||
|
||||
if let subscriptionResultError = subscriptionResult.error {
|
||||
return .Error(subscriptionResultError)
|
||||
}
|
||||
|
||||
let connectResult: Result<Void> = subscriptionResult >>> {
|
||||
let state = self.parent.state
|
||||
|
||||
return self.parent.lock.calculateLocked {
|
||||
if state.count == 0 {
|
||||
return self.parent.source.connect() >== { disposable in
|
||||
self.parent.state.count = 1
|
||||
self.parent.state.connectableSubscription = disposable
|
||||
return SuccessResult
|
||||
}
|
||||
}
|
||||
else {
|
||||
self.parent.state.count = state.count + 1
|
||||
return SuccessResult
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let connectResultError = connectResult.error {
|
||||
// cleanup registration
|
||||
(*subscriptionResult).dispose()
|
||||
return .Error(connectResultError)
|
||||
}
|
||||
|
||||
return success(AnonymousDisposable {
|
||||
self.parent.lock.performLocked {
|
||||
let state = self.parent.state
|
||||
if state.count == 1 {
|
||||
state.connectableSubscription!.dispose()
|
||||
self.parent.state.count = 0
|
||||
self.parent.state.connectableSubscription = nil
|
||||
}
|
||||
else if state.count > 1 {
|
||||
self.parent.state.count = state.count - 1
|
||||
}
|
||||
else {
|
||||
rxFatalError("Something went wrong with RefCount disposing mechanism")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func on(event: Event<Element>) -> Result<Void> {
|
||||
let observer = state.observer
|
||||
|
||||
switch event {
|
||||
case .Next: return observer.on(event)
|
||||
case .Error: fallthrough
|
||||
case .Completed:
|
||||
let result = observer.on(event)
|
||||
self.dispose()
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RefCount<Element>: Producer<Element> {
|
||||
typealias State = (count: Int, connectableSubscription: Disposable?)
|
||||
|
||||
var lock = Lock()
|
||||
|
||||
var state: State = (
|
||||
count: 0,
|
||||
connectableSubscription: nil
|
||||
)
|
||||
|
||||
let source: ConnectableObservableType<Element>
|
||||
|
||||
init(source: ConnectableObservableType<Element>) {
|
||||
self.source = source
|
||||
}
|
||||
|
||||
override func run(observer: ObserverOf<Element>, cancel: Disposable, setSink: (Disposable) -> Void) -> Result<Disposable> {
|
||||
let sink = RefCount_(parent: self, observer: observer, cancel: cancel)
|
||||
setSink(sink)
|
||||
return sink.run()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
//
|
||||
// ScheduledObserver.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 4/5/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
enum ScheduledState: Int {
|
||||
case Stopped = 0
|
||||
case Running = 1
|
||||
case Pending = 2
|
||||
case Faulted = 9
|
||||
}
|
||||
|
||||
public class ScheduledObserver<Element> : ObserverBase<Element> {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
//
|
||||
// Select.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/15/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class Select_<ElementType, ResultType> : Sink<ResultType>, ObserverClassType {
|
||||
let parent: Select<ElementType, ResultType>
|
||||
|
||||
init(parent: Select<ElementType, ResultType>, observer: ObserverOf<ResultType>, cancel: Disposable) {
|
||||
self.parent = parent
|
||||
super.init(observer: observer, cancel: cancel)
|
||||
}
|
||||
|
||||
func select(element: ElementType) -> Result<ResultType> {
|
||||
return abstractMethod()
|
||||
}
|
||||
|
||||
func on(event: Event<ElementType>) -> Result<Void> {
|
||||
let observer = super.state.observer
|
||||
|
||||
switch event {
|
||||
case .Next(let element):
|
||||
let sendValueResult: Result<Void> = select(element.value) >== { value in
|
||||
return observer.on(.Next(Box(value)))
|
||||
}
|
||||
|
||||
return sendValueResult >>! { e -> Result<Void> in
|
||||
let result: Result<Void> = observer.on(.Error(e)) >>> { .Error(e) }
|
||||
self.dispose()
|
||||
return result
|
||||
}
|
||||
case .Error(let error):
|
||||
let result = observer.on(.Error(error))
|
||||
self.dispose()
|
||||
return result
|
||||
case .Completed:
|
||||
let result = observer.on(.Completed)
|
||||
self.dispose()
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Select_1<ElementType, ResultType> : Select_<ElementType, ResultType> {
|
||||
|
||||
override init(parent: Select<ElementType, ResultType>, observer: ObserverOf<ResultType>, cancel: Disposable) {
|
||||
super.init(parent: parent, observer: observer, cancel: cancel)
|
||||
}
|
||||
|
||||
override func select(element: ElementType) -> Result<ResultType> {
|
||||
return (self.parent.selector1!)(element)
|
||||
}
|
||||
}
|
||||
|
||||
class Select_2<ElementType, ResultType> : Select_<ElementType, ResultType> {
|
||||
var index = 0
|
||||
|
||||
override init(parent: Select<ElementType, ResultType>, observer: ObserverOf<ResultType>, cancel: Disposable) {
|
||||
super.init(parent: parent, observer: observer, cancel: cancel)
|
||||
}
|
||||
override func select(element: ElementType) -> Result<ResultType> {
|
||||
return (self.parent.selector2!)(element, index++)
|
||||
}
|
||||
}
|
||||
|
||||
class Select<ElementType, ResultType>: Producer<ResultType> {
|
||||
typealias Element = ElementType
|
||||
typealias Selector1 = (Element) -> Result<ResultType>
|
||||
typealias Selector2 = (Element, Int) -> Result<ResultType>
|
||||
|
||||
let source: Observable<Element>
|
||||
|
||||
let selector1: Selector1?
|
||||
let selector2: Selector2?
|
||||
|
||||
init(source: Observable<Element>, selector: Selector1) {
|
||||
self.source = source
|
||||
self.selector1 = selector
|
||||
self.selector2 = nil
|
||||
}
|
||||
|
||||
init(source: Observable<Element>, selector: Selector2) {
|
||||
self.source = source
|
||||
self.selector2 = selector
|
||||
self.selector1 = nil
|
||||
}
|
||||
|
||||
override func run(observer: ObserverOf<ResultType>, cancel: Disposable, setSink: (Disposable) -> Void) -> Result<Disposable> {
|
||||
var sink: Select_<ElementType, ResultType>
|
||||
if let selector1 = self.selector1 {
|
||||
sink = Select_1(parent: self, observer: observer, cancel: cancel)
|
||||
}
|
||||
else {
|
||||
sink = Select_2(parent: self, observer: observer, cancel: cancel)
|
||||
}
|
||||
|
||||
setSink(sink)
|
||||
|
||||
return self.source.subscribeSafe(ObserverOf(sink))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
//
|
||||
// Sink.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/19/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct Sink_<ElementType>: ObserverType {
|
||||
typealias Element = ElementType
|
||||
|
||||
let sink: Sink<Element>
|
||||
|
||||
init(sink: Sink<Element>) {
|
||||
self.sink = sink
|
||||
}
|
||||
|
||||
mutating func on(event: Event<Element>) -> Result<Void> {
|
||||
let result = sink.state.observer.on(event)
|
||||
switch event {
|
||||
case .Next:
|
||||
return result
|
||||
case .Completed: fallthrough
|
||||
case .Error:
|
||||
self.sink.dispose()
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Sink<ElementType> : Disposable {
|
||||
private typealias Element = ElementType
|
||||
|
||||
typealias State = (observer: ObserverOf<ElementType>, cancel: Disposable, disposed: Bool)
|
||||
|
||||
private var lock = Lock()
|
||||
private var _state: State
|
||||
|
||||
var observer: ObserverOf<ElementType> {
|
||||
get {
|
||||
return lock.calculateLocked { _state.observer }
|
||||
}
|
||||
}
|
||||
|
||||
var cancel: Disposable {
|
||||
get {
|
||||
return lock.calculateLocked { _state.cancel }
|
||||
}
|
||||
}
|
||||
|
||||
var state: State {
|
||||
get {
|
||||
return lock.calculateLocked { _state }
|
||||
}
|
||||
}
|
||||
|
||||
init(observer: ObserverOf<ElementType>, cancel: Disposable) {
|
||||
#if DEBUG
|
||||
OSAtomicIncrement32(&resourceCount)
|
||||
#endif
|
||||
_state = (
|
||||
observer: observer,
|
||||
cancel: cancel,
|
||||
disposed: false
|
||||
)
|
||||
}
|
||||
|
||||
func getForwarder() -> Sink_<Element> {
|
||||
return Sink_(sink: self)
|
||||
}
|
||||
|
||||
func dispose() {
|
||||
var cancel: Disposable? = lock.calculateLocked {
|
||||
if _state.disposed {
|
||||
return nil
|
||||
}
|
||||
|
||||
var cancel = _state.cancel
|
||||
|
||||
_state.disposed = true
|
||||
_state.observer = ObserverOf(NopObserver())
|
||||
_state.cancel = DefaultDisposable()
|
||||
|
||||
return cancel
|
||||
}
|
||||
|
||||
if let cancel = cancel {
|
||||
cancel.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
#if DEBUG
|
||||
OSAtomicDecrement32(&resourceCount)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
//
|
||||
// Subject.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/11/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class Subscription<Element> : Disposable {
|
||||
typealias ObserverType = ObserverOf<Element>
|
||||
typealias KeyType = Bag<Void>.KeyType
|
||||
|
||||
private let subject : Subject<Element>
|
||||
private var key: KeyType
|
||||
|
||||
|
||||
private var lock = Lock()
|
||||
private var observer: ObserverType?
|
||||
|
||||
init(subject: Subject<Element>, key: KeyType, observer: ObserverType) {
|
||||
self.key = key
|
||||
self.subject = subject
|
||||
self.observer = observer
|
||||
}
|
||||
|
||||
func dispose() {
|
||||
lock.performLocked {
|
||||
if let observer = self.observer {
|
||||
self.subject.unsubscribe(self.key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class Subject<Element> : SubjectType<Element, Element>, Disposable {
|
||||
typealias ObserverType = ObserverOf<Element>
|
||||
typealias KeyType = Bag<Void>.KeyType
|
||||
typealias Observers = Bag<ObserverType>
|
||||
typealias State = (
|
||||
disposed: Bool,
|
||||
observers: Observers,
|
||||
stoppedEvent: Event<Element>?
|
||||
)
|
||||
|
||||
private var lock = Lock()
|
||||
private var state: State = (
|
||||
disposed: false,
|
||||
observers: Observers(),
|
||||
stoppedEvent: nil
|
||||
)
|
||||
|
||||
public override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
public func dispose() {
|
||||
self.lock.performLocked {
|
||||
state.disposed = true
|
||||
}
|
||||
}
|
||||
|
||||
public override func on(event: Event<Element>) -> Result<Void> {
|
||||
switch event {
|
||||
case .Next(let value):
|
||||
let observers = lock.calculateLocked { () -> [ObserverType]? in
|
||||
let state = self.state
|
||||
let shouldReturnImmediatelly = state.disposed || state.stoppedEvent != nil
|
||||
let observers: [ObserverType]? = shouldReturnImmediatelly ? nil : state.observers.all
|
||||
|
||||
return observers
|
||||
}
|
||||
|
||||
if let observers = observers {
|
||||
return dispatch(event, observers)
|
||||
}
|
||||
else {
|
||||
return SuccessResult
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
let observers: [ObserverType] = lock.calculateLocked {
|
||||
let state = self.state
|
||||
|
||||
var observers = self.state.observers.all
|
||||
|
||||
switch event {
|
||||
case .Completed: fallthrough
|
||||
case .Error:
|
||||
if state.stoppedEvent == nil {
|
||||
self.state.stoppedEvent = event
|
||||
self.state.observers.removeAll()
|
||||
}
|
||||
default:
|
||||
rxFatalError("Something went wrong")
|
||||
}
|
||||
|
||||
return observers
|
||||
}
|
||||
|
||||
return dispatch(event, observers)
|
||||
}
|
||||
|
||||
|
||||
public override func subscribe(observer: ObserverOf<Element>) -> Result<Disposable> {
|
||||
return lock.calculateLocked {
|
||||
if let stoppedEvent = state.stoppedEvent {
|
||||
return observer.on(stoppedEvent) >>> {
|
||||
return success(DefaultDisposable())
|
||||
}
|
||||
}
|
||||
|
||||
if state.disposed {
|
||||
return .Error(DisposedError)
|
||||
}
|
||||
|
||||
let key = state.observers.put(observer)
|
||||
return success(Subscription(subject: self, key: key, observer: observer))
|
||||
}
|
||||
}
|
||||
|
||||
func unsubscribe(key: KeyType) {
|
||||
self.lock.performLocked {
|
||||
let observer = state.observers.removeKey(key)
|
||||
if observer == nil {
|
||||
rxFatalError("Something went wrong with dispose")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
//
|
||||
// Switch.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/12/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class Switch_<ElementType> : Sink<ElementType>, ObserverClassType {
|
||||
typealias Element = Observable<ElementType>
|
||||
typealias SwitchState = (
|
||||
subscription: SingleAssignmentDisposable,
|
||||
innerSubscription: SerialDisposable,
|
||||
stopped: Bool,
|
||||
latest: Int,
|
||||
hasLatest: Bool
|
||||
)
|
||||
|
||||
let parent: Switch<ElementType>
|
||||
|
||||
var lock = Lock()
|
||||
var switchState: SwitchState
|
||||
|
||||
init(parent: Switch<ElementType>, observer: ObserverOf<ElementType>, cancel: Disposable) {
|
||||
self.parent = parent
|
||||
self.switchState = (
|
||||
subscription: SingleAssignmentDisposable(),
|
||||
innerSubscription: SerialDisposable(),
|
||||
stopped: false,
|
||||
latest: 0,
|
||||
hasLatest: false
|
||||
)
|
||||
super.init(observer: observer, cancel: cancel)
|
||||
}
|
||||
|
||||
func run() -> Result<Disposable> {
|
||||
return self.parent.sources.subscribeSafe(ObserverOf(self)) >== { subscription in
|
||||
let switchState = self.switchState
|
||||
switchState.subscription.setDisposable(subscription)
|
||||
return success(CompositeDisposable(switchState.subscription, switchState.innerSubscription))
|
||||
}
|
||||
}
|
||||
|
||||
func on(event: Event<Element>) -> Result<Void> {
|
||||
switch event {
|
||||
case .Next(let observable):
|
||||
let latest: Int = self.lock.calculateLocked {
|
||||
self.switchState.hasLatest = true
|
||||
self.switchState.latest = self.switchState.latest + 1
|
||||
return self.switchState.latest
|
||||
}
|
||||
|
||||
let d = SingleAssignmentDisposable()
|
||||
self.switchState.innerSubscription.setDisposable(d)
|
||||
|
||||
let observer = ObserverOf(SwitchIter(parent: self, id: latest, _self: d))
|
||||
return observable.value.subscribeSafe(observer) >== { disposable in
|
||||
d.setDisposable(disposable)
|
||||
return SuccessResult
|
||||
}
|
||||
case .Error(let error):
|
||||
let result = self.lock.calculateLocked {
|
||||
return self.state.observer.on(.Error(error))
|
||||
}
|
||||
self.dispose()
|
||||
return result
|
||||
case .Completed:
|
||||
return self.lock.calculateLocked {
|
||||
self.switchState.stopped = true
|
||||
|
||||
self.switchState.subscription.dispose()
|
||||
|
||||
var result = SuccessResult
|
||||
if !self.switchState.hasLatest {
|
||||
result = self.state.observer.on(.Completed)
|
||||
self.dispose()
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SwitchIter<ElementType> : ObserverClassType {
|
||||
typealias Element = ElementType
|
||||
|
||||
let parent: Switch_<Element>
|
||||
let id: Int
|
||||
let _self: Disposable
|
||||
|
||||
init(parent: Switch_<Element>, id: Int, _self: Disposable) {
|
||||
self.parent = parent
|
||||
self.id = id
|
||||
self._self = _self
|
||||
}
|
||||
|
||||
func on(event: Event<ElementType>) -> Result<Void> {
|
||||
return parent.lock.calculateLocked { state in
|
||||
let switchState = self.parent.switchState
|
||||
|
||||
switch event {
|
||||
case .Next: break
|
||||
case .Error: fallthrough
|
||||
case .Completed: self._self.dispose()
|
||||
}
|
||||
|
||||
if switchState.latest != self.id {
|
||||
return success(state)
|
||||
}
|
||||
|
||||
let observer = self.parent.state.observer
|
||||
|
||||
switch event {
|
||||
case .Next:
|
||||
return observer.on(event)
|
||||
case .Error:
|
||||
let result = observer.on(event)
|
||||
self.parent.dispose()
|
||||
return result
|
||||
case .Completed:
|
||||
parent.switchState.hasLatest = false
|
||||
if switchState.stopped {
|
||||
let result = observer.on(event)
|
||||
self.parent.dispose()
|
||||
return result
|
||||
}
|
||||
else {
|
||||
return SuccessResult
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Switch<Element> : Producer<Element> {
|
||||
let sources: Observable<Observable<Element>>
|
||||
|
||||
init(sources: Observable<Observable<Element>>) {
|
||||
self.sources = sources
|
||||
}
|
||||
|
||||
override func run(observer: ObserverOf<Element>, cancel: Disposable, setSink: (Disposable) -> Void) -> Result<Disposable> {
|
||||
let sink = Switch_(parent: self, observer: observer, cancel: cancel)
|
||||
setSink(sink)
|
||||
return sink.run()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
//
|
||||
// TailRecursiveSink.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/21/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class TailRecursiveSink<ElementType> : Sink<ElementType>, ObserverClassType {
|
||||
typealias Element = ElementType
|
||||
typealias StackElementType = (generator: GeneratorOf<Observable<Element>>, length: Int)
|
||||
|
||||
var stack: [StackElementType] = []
|
||||
var disposed: Bool = false
|
||||
var subscription: SerialDisposable = SerialDisposable()
|
||||
|
||||
// this is thread safe object
|
||||
var gate: AsyncLock = AsyncLock()
|
||||
|
||||
override init(observer: ObserverOf<Element>, cancel: Disposable) {
|
||||
super.init(observer: observer, cancel: cancel)
|
||||
}
|
||||
|
||||
func run(sources: [Observable<Element>]) -> Result<Disposable> {
|
||||
let generator: GeneratorOf<Observable<Element>> = GeneratorOf(sources.generate())
|
||||
self.stack.append((generator: generator, length: sources.count))
|
||||
|
||||
let stateSnapshot = self.state
|
||||
|
||||
return scheduleMoveNext() >>> {
|
||||
success(CompositeDisposable(
|
||||
self.subscription,
|
||||
stateSnapshot.cancel,
|
||||
AnonymousDisposable {
|
||||
self.disposePrivate()
|
||||
}
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
func scheduleMoveNext() -> Result<Void> {
|
||||
return schedule {
|
||||
self.moveNext()
|
||||
}
|
||||
}
|
||||
|
||||
// simple implementation for now
|
||||
func schedule(action: () -> Result<Void>) -> Result<Void> {
|
||||
return self.gate.wait(action)
|
||||
}
|
||||
|
||||
func moveNext() -> Result<Void> {
|
||||
var next: Observable<Element>? = nil;
|
||||
|
||||
do {
|
||||
if self.stack.count == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
if disposed {
|
||||
return SuccessResult
|
||||
}
|
||||
|
||||
var (e, l) = stack.last!
|
||||
|
||||
let current = e.next()
|
||||
|
||||
if current == nil {
|
||||
stack.removeLast()
|
||||
continue;
|
||||
}
|
||||
|
||||
let r = l - 1
|
||||
|
||||
stack.removeLast()
|
||||
stack.append((generator: e, length: r))
|
||||
|
||||
next = current
|
||||
|
||||
if r == 0 {
|
||||
stack.removeLast()
|
||||
}
|
||||
|
||||
let nextSeq = extract(next!)
|
||||
|
||||
if let nextSeq = nextSeq {
|
||||
let generator = GeneratorOf(nextSeq.generate())
|
||||
let length = nextSeq.count
|
||||
|
||||
next = nil
|
||||
}
|
||||
} while next == nil
|
||||
|
||||
if next == nil {
|
||||
return done()
|
||||
}
|
||||
|
||||
let d = SingleAssignmentDisposable()
|
||||
subscription.setDisposable(d)
|
||||
return next!.subscribeSafe(ObserverOf(self)) >== { subscription in
|
||||
d.setDisposable(subscription)
|
||||
}
|
||||
}
|
||||
|
||||
private func disposePrivate() {
|
||||
disposed = true
|
||||
|
||||
stack.removeAll(keepCapacity: false)
|
||||
}
|
||||
|
||||
func done() -> Result<Void> {
|
||||
let result = state.observer.on(.Completed)
|
||||
self.dispose()
|
||||
return result
|
||||
}
|
||||
|
||||
func extract(observable: Observable<Element>) -> [Observable<Element>]? {
|
||||
return abstractMethod()
|
||||
}
|
||||
|
||||
func on(event: Event<Element>) -> Result<Void> {
|
||||
return abstractMethod()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
//
|
||||
// Throttle.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/22/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class Throttle_<Element, SchedulerType: Scheduler> : Sink<Element>, ObserverClassType {
|
||||
typealias ParentType = Throttle<Element, SchedulerType>
|
||||
typealias ThrottleState = (
|
||||
value: Element?,
|
||||
cancellable: SerialDisposable,
|
||||
id: UInt64
|
||||
)
|
||||
|
||||
let parent: ParentType
|
||||
|
||||
var lock = Lock()
|
||||
var throttleState: ThrottleState = (
|
||||
value: nil,
|
||||
cancellable: SerialDisposable(),
|
||||
id: 0
|
||||
)
|
||||
|
||||
init(parent: ParentType, observer: ObserverOf<Element>, cancel: Disposable) {
|
||||
self.parent = parent
|
||||
|
||||
super.init(observer: observer, cancel: cancel)
|
||||
}
|
||||
|
||||
func run() -> Result<Disposable> {
|
||||
let cancellable = self.throttleState.cancellable
|
||||
return parent.source.subscribeSafe(ObserverOf(self)) >== { subscription in
|
||||
return success(CompositeDisposable(subscription, cancellable))
|
||||
}
|
||||
}
|
||||
|
||||
func on(event: Event<Element>) -> Result<Void> {
|
||||
switch event {
|
||||
case .Next:
|
||||
break
|
||||
case .Error: fallthrough
|
||||
case .Completed:
|
||||
throttleState.cancellable.dispose()
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
var (latestId: UInt64, observer: ObserverOf<Element>, oldValue: Element?) = self.lock.calculateLocked {
|
||||
let observer = self.observer
|
||||
|
||||
var oldValue = self.throttleState.value
|
||||
|
||||
switch event {
|
||||
case .Next(let boxedValue):
|
||||
self.throttleState.value = boxedValue.value
|
||||
case .Error(let error):
|
||||
self.dispose()
|
||||
self.throttleState.value = nil
|
||||
case .Completed:
|
||||
self.dispose()
|
||||
self.throttleState.value = nil
|
||||
}
|
||||
|
||||
self.throttleState.id = self.throttleState.id + 1
|
||||
return (self.throttleState.id, observer, oldValue)
|
||||
}
|
||||
|
||||
|
||||
switch event {
|
||||
case .Next(let boxedValue):
|
||||
let d = SingleAssignmentDisposable()
|
||||
self.throttleState.cancellable.setDisposable(d)
|
||||
|
||||
let scheduler = self.parent.scheduler
|
||||
let dueTime = self.parent.dueTime
|
||||
|
||||
return scheduler.schedule(latestId, dueTime: dueTime, action: { (id) in
|
||||
return self.propagate()
|
||||
}) >== { disposeTimer in
|
||||
d.setDisposable(disposeTimer)
|
||||
return SuccessResult
|
||||
}
|
||||
case .Error(let error):
|
||||
return observer.on(.Error(error))
|
||||
case .Completed:
|
||||
var sendResult: Result<Void>
|
||||
if let oldValue = oldValue {
|
||||
sendResult = observer.on(.Next(Box(oldValue)))
|
||||
}
|
||||
else {
|
||||
sendResult = SuccessResult
|
||||
}
|
||||
return sendResult >>> {
|
||||
return observer.on(.Completed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func propagate() -> Result<Void> {
|
||||
var originalValue: Element? = self.lock.calculateLocked {
|
||||
var originalValue = self.throttleState.value
|
||||
self.throttleState.value = nil
|
||||
return originalValue
|
||||
}
|
||||
|
||||
if let value = originalValue {
|
||||
return self.observer.on(.Next(Box(value)))
|
||||
}
|
||||
else {
|
||||
return SuccessResult
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Throttle<Element, SchedulerType: Scheduler> : Producer<Element> {
|
||||
|
||||
let source: Observable<Element>
|
||||
let dueTime: SchedulerType.TimeInterval
|
||||
let scheduler: SchedulerType
|
||||
|
||||
init(source: Observable<Element>, dueTime: SchedulerType.TimeInterval, scheduler: SchedulerType) {
|
||||
self.source = source
|
||||
self.dueTime = dueTime
|
||||
self.scheduler = scheduler
|
||||
}
|
||||
|
||||
override func run(observer: ObserverOf<Element>, cancel: Disposable, setSink: (Disposable) -> Void) -> Result<Disposable> {
|
||||
let sink = Throttle_(parent: self, observer: observer, cancel: cancel)
|
||||
setSink(sink)
|
||||
return sink.run()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
//
|
||||
// Variable.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/28/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class Variable<Element>: Subject<Element> {
|
||||
typealias VariableState = Element
|
||||
|
||||
var lock = Lock()
|
||||
var replayEvent: Event<Element>? = nil
|
||||
|
||||
public init(_ initialEvent: Event<Element>) {
|
||||
self.replayEvent = initialEvent
|
||||
super.init()
|
||||
}
|
||||
|
||||
public override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
public override func on(event: Event<Element>) -> Result<Void> {
|
||||
switch event {
|
||||
case .Next:
|
||||
lock.performLocked {
|
||||
self.replayEvent = event
|
||||
}
|
||||
default: break
|
||||
}
|
||||
|
||||
return super.on(event)
|
||||
}
|
||||
|
||||
public override func subscribe(observer: ObserverOf<Element>) -> Result<Disposable> {
|
||||
var result: Result<Void>
|
||||
|
||||
var currentValue = self.lock.calculateLocked { self.replayEvent }
|
||||
|
||||
if let currentValue = currentValue {
|
||||
result = observer.on(currentValue)
|
||||
}
|
||||
else {
|
||||
result = SuccessResult
|
||||
}
|
||||
|
||||
if let error = result.error {
|
||||
dispose()
|
||||
return .Error(error)
|
||||
}
|
||||
|
||||
return super.subscribe(observer)
|
||||
}
|
||||
}
|
||||
|
||||
public func << <E>(variable: Variable<E>, element: E) {
|
||||
variable.on(.Next(Box(element)))
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
//
|
||||
// WhereObservable.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/17/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class WhereObserver<Element>: ObserverBase<Element> {
|
||||
typealias Predicate = (Element) -> Result<Bool>
|
||||
|
||||
let observer: ObserverOf<Element>
|
||||
let predicate: Predicate
|
||||
|
||||
init(observer: ObserverOf<Element>, predicate: Predicate) {
|
||||
self.observer = observer
|
||||
self.predicate = predicate
|
||||
}
|
||||
|
||||
override func onCore(event: Event<Element>) -> Result<Void> {
|
||||
switch event {
|
||||
case .Next(let value):
|
||||
return (predicate(value.value) >>! { e in
|
||||
return self.observer.on(.Error(e)) >>> { .Error(e) }
|
||||
}) >== { satisfies in
|
||||
return satisfies
|
||||
? self.observer.on(event)
|
||||
: SuccessResult
|
||||
}
|
||||
case .Completed: fallthrough
|
||||
case .Error: return observer.on(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class WhereObservable<Element> : ObservableBase<Element> {
|
||||
typealias Predicate = (Element) -> Result<Bool>
|
||||
|
||||
let source: Observable<Element>
|
||||
let predicate: Predicate
|
||||
|
||||
init(source: Observable<Element>, predicate: Predicate) {
|
||||
self.source = source
|
||||
self.predicate = predicate
|
||||
}
|
||||
|
||||
func compose(predicate: Predicate) -> WhereObservable {
|
||||
// too slow
|
||||
return WhereObservable(source: source, predicate: { lift({ $0 && $1 }) (self.predicate($0), predicate($0)) })
|
||||
}
|
||||
|
||||
override func subscribeCore(observer: ObserverOf<Element>) -> Result<Disposable> {
|
||||
return source.subscribe(ObserverOf(WhereObserver(observer: observer, predicate: predicate)))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
//
|
||||
// Observable+Aggregate.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/22/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
// aggregate
|
||||
|
||||
public func aggregateOrDie<E, A, R>
|
||||
(seed: A, accumulator: (A, E) -> Result<A>, resultSelector: (A) -> Result<R>)
|
||||
-> (Observable<E> -> Observable<R>) {
|
||||
return { source in
|
||||
return Aggregate(source: source, seed: seed, accumulator: accumulator, resultSelector: resultSelector)
|
||||
}
|
||||
}
|
||||
|
||||
public func aggregateOrDie<E, A>
|
||||
(seed: A, accumulator: (A, E) -> Result<A>)
|
||||
-> (Observable<E> -> Observable<A>) {
|
||||
return { source in
|
||||
return Aggregate(source: source, seed: seed, accumulator: accumulator, resultSelector: { success($0) })
|
||||
}
|
||||
}
|
||||
|
||||
public func aggregate<E, A, R>
|
||||
(seed: A, accumulator: (A, E) -> A, resultSelector: (A) -> R)
|
||||
-> (Observable<E> -> Observable<R>) {
|
||||
return { source in
|
||||
return Aggregate(source: source, seed: seed, accumulator: { success(accumulator($0, $1)) }, resultSelector: { success(resultSelector($0)) })
|
||||
}
|
||||
}
|
||||
|
||||
public func aggregate<E, A>
|
||||
(seed: A, accumulator: (A, E) -> A)
|
||||
-> (Observable<E> -> Observable<A>) {
|
||||
return { source in
|
||||
return Aggregate(source: source, seed: seed, accumulator: { success(accumulator($0, $1)) }, resultSelector: { success($0) })
|
||||
}
|
||||
}
|
||||
|
||||
// foldl
|
||||
|
||||
public func foldlOrDie<E, A, R>
|
||||
(seed: A, accumulator: (A, E) -> Result<A>, resultSelector: (A) -> Result<R>)
|
||||
-> (Observable<E> -> Observable<R>) {
|
||||
return { source in
|
||||
return Aggregate(source: source, seed: seed, accumulator: accumulator, resultSelector: resultSelector)
|
||||
}
|
||||
}
|
||||
|
||||
public func foldlOrDie<E, A>
|
||||
(seed: A, accumulator: (A, E) -> Result<A>)
|
||||
-> (Observable<E> -> Observable<A>) {
|
||||
return { source in
|
||||
return Aggregate(source: source, seed: seed, accumulator: accumulator, resultSelector: { success($0) })
|
||||
}
|
||||
}
|
||||
|
||||
public func foldl<E, A, R>
|
||||
(seed: A, accumulator: (A, E) -> A, resultSelector: (A) -> R)
|
||||
-> (Observable<E> -> Observable<R>) {
|
||||
return { source in
|
||||
return Aggregate(source: source, seed: seed, accumulator: { success(accumulator($0, $1)) }, resultSelector: { success(resultSelector($0)) })
|
||||
}
|
||||
}
|
||||
|
||||
public func foldl<E, A>
|
||||
(seed: A, accumulator: (A, E) -> A)
|
||||
-> (Observable<E> -> Observable<A>) {
|
||||
return { source in
|
||||
return Aggregate(source: source, seed: seed, accumulator: { success(accumulator($0, $1)) }, resultSelector: { success($0) })
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// Observable+Binding.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/1/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
// multicast
|
||||
|
||||
public func multicast<E, R>
|
||||
(subject: SubjectType<E, R>)
|
||||
-> (Observable<E> -> ConnectableObservableType<R>) {
|
||||
return { source in
|
||||
return ConnectableObservable(source: source, subject: subject)
|
||||
}
|
||||
}
|
||||
|
||||
// refcount
|
||||
|
||||
public func refCount<E>
|
||||
(source: ConnectableObservableType<E>)
|
||||
-> Observable<E> {
|
||||
return RefCount(source: source)
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// Observable+Concurrency.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/15/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
// Currently only simple observing is implemented.
|
||||
//
|
||||
// On client devices most common use case for observeOn would be to execute some work on background thread
|
||||
// or return result to main thread.
|
||||
//
|
||||
// `observeSingleOn` is optimized for that specific purpose. It assumes that sequence will have one element
|
||||
// and in cases it has more then one element it will throw an exception.
|
||||
//
|
||||
// This is a huge performance win considering most general case.
|
||||
//
|
||||
// General slower version of `observeOn` will not be implemented until needed.
|
||||
//
|
||||
// Even though it looks like naive implementation of general `observeOn` using simple `schedule`
|
||||
// for each event will work, this is not the case.
|
||||
|
||||
public func observeSingleOn<E>
|
||||
(scheduler: ImmediateScheduler)
|
||||
-> ((Observable<E>) -> Observable<E>) {
|
||||
return { source in
|
||||
return ObserveSingleOn(source: source, scheduler: scheduler)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// Observable+Creation.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/21/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
// create
|
||||
|
||||
public func create<E>(subscribe: (ObserverOf<E>) -> Result<Disposable>) -> Observable<E> {
|
||||
return AnonymousObservable(subscribe)
|
||||
}
|
||||
|
||||
// empty
|
||||
|
||||
public func empty<E>() -> Observable<E> {
|
||||
return AnonymousObservable { observer in
|
||||
let result : Result<Void> = observer.on(.Completed)
|
||||
return result >>> { (DefaultDisposable()) }
|
||||
}
|
||||
}
|
||||
|
||||
// never
|
||||
|
||||
public func never<E>() -> Observable<E> {
|
||||
return AnonymousObservable { observer in
|
||||
return success(DefaultDisposable())
|
||||
}
|
||||
}
|
||||
|
||||
// return
|
||||
|
||||
public func returnElement<E>(value: E) -> Observable<E> {
|
||||
return AnonymousObservable { observer in
|
||||
return observer.on(.Next(Box(value))) >>> { observer.on(.Completed) } >>> { (DefaultDisposable()) }
|
||||
}
|
||||
}
|
||||
|
||||
public func returnElement<E>(values: E ...) -> Observable<E> {
|
||||
return AnonymousObservable { observer in
|
||||
var result = SuccessResult
|
||||
|
||||
for element in values {
|
||||
result = result >>> { observer.on(.Next(Box(element))) }
|
||||
}
|
||||
|
||||
return (result >>> { observer.on(.Completed) }) >>> { (DefaultDisposable()) }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
//
|
||||
// Observable+Multiple.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/12/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
// switch
|
||||
|
||||
public func switchLatest<T>
|
||||
(sources: Observable<Observable<T>>)
|
||||
-> Observable<T> {
|
||||
|
||||
// swift doesn't have co/contravariance
|
||||
return Switch(sources: sources)
|
||||
}
|
||||
|
||||
// combine latest
|
||||
|
||||
public func combineLatestOrDie<E1, E2, R>
|
||||
(with: Observable<E1>, resultSelector: (E1, E2) -> Result<R>)
|
||||
-> (Observable<E2> -> Observable<R>) {
|
||||
return { source in
|
||||
return CombineLatest(observable1: with, observable2: source, selector: resultSelector)
|
||||
}
|
||||
}
|
||||
|
||||
public func combineLatest<E1, E2, R>
|
||||
(with: Observable<E1>, resultSelector: (E1, E2) -> R)
|
||||
-> (Observable<E2> -> Observable<R>) {
|
||||
return { source in
|
||||
return CombineLatest(observable1: with, observable2: source, selector: { success(resultSelector($0, $1)) })
|
||||
}
|
||||
}
|
||||
|
||||
// concat
|
||||
|
||||
public func concat<E>
|
||||
(sources: [Observable<E>])
|
||||
-> Observable<E> {
|
||||
return Concat(sources: sources)
|
||||
}
|
||||
|
||||
// merge
|
||||
|
||||
public func merge<E>
|
||||
(sources: Observable<Observable<E>>)
|
||||
-> Observable<E> {
|
||||
return Merge(sources: sources, maxConcurrent: 0)
|
||||
}
|
||||
|
||||
public func merge<E>
|
||||
(maxConcurrent: Int)
|
||||
-> (Observable<Observable<E>> -> Observable<E>) {
|
||||
return { sources in
|
||||
return Merge(sources: sources, maxConcurrent: maxConcurrent)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
//
|
||||
// Observable+Single.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/14/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
// as observable
|
||||
|
||||
public func asObservable<E>
|
||||
(source: Observable<E>) -> Observable<E> {
|
||||
if let asObservable = source as? AsObservable<E> {
|
||||
return asObservable.omega()
|
||||
}
|
||||
else {
|
||||
return AsObservable(source: source)
|
||||
}
|
||||
}
|
||||
|
||||
// distinct until changed
|
||||
|
||||
public func distinctUntilChangedOrDie<E: Equatable>(source: Observable<E>)
|
||||
-> Observable<E>{
|
||||
return distinctUntilChangedOrDie({ success($0) }, { success($0 == $1) })(source)
|
||||
}
|
||||
|
||||
public func distinctUntilChangedOrDie<E, K: Equatable>
|
||||
(keySelector: (E) -> Result<K>)
|
||||
-> (Observable<E> -> Observable<E>) {
|
||||
return { source in
|
||||
return distinctUntilChangedOrDie(keySelector, { success($0 == $1) })(source)
|
||||
}
|
||||
}
|
||||
|
||||
public func distinctUntilChangedOrDie<E>
|
||||
(comparer: (lhs: E, rhs: E) -> Result<Bool>)
|
||||
-> (Observable<E> -> Observable<E>) {
|
||||
return { source in
|
||||
return distinctUntilChangedOrDie({ success($0) }, comparer)(source)
|
||||
}
|
||||
}
|
||||
|
||||
public func distinctUntilChangedOrDie<E, K>
|
||||
(keySelector: (E) -> Result<K>, comparer: (lhs: K, rhs: K) -> Result<Bool>)
|
||||
-> (Observable<E> -> Observable<E>) {
|
||||
return { source in
|
||||
return DistinctUntilChanged(source: source, selector: keySelector, comparer: comparer)
|
||||
}
|
||||
}
|
||||
|
||||
public func distinctUntilChanged<E: Equatable>(source: Observable<E>)
|
||||
-> Observable<E> {
|
||||
return distinctUntilChanged({ $0 }, { ($0 == $1) })(source)
|
||||
}
|
||||
|
||||
public func distinctUntilChanged<E, K: Equatable>
|
||||
(keySelector: (E) -> K)
|
||||
-> (Observable<E> -> Observable<E>) {
|
||||
return { source in
|
||||
return distinctUntilChanged(keySelector, { ($0 == $1) })(source)
|
||||
}
|
||||
}
|
||||
|
||||
public func distinctUntilChanged<E>
|
||||
(comparer: (lhs: E, rhs: E) -> Bool)
|
||||
-> (Observable<E> -> Observable<E>) {
|
||||
return { source in
|
||||
return distinctUntilChanged({ ($0) }, comparer)(source)
|
||||
}
|
||||
}
|
||||
|
||||
public func distinctUntilChanged<E, K>
|
||||
(keySelector: (E) -> K, comparer: (lhs: K, rhs: K) -> Bool)
|
||||
-> (Observable<E> -> Observable<E>) {
|
||||
return { source in
|
||||
return DistinctUntilChanged(source: source, selector: {success(keySelector($0)) }, comparer: { success(comparer(lhs: $0, rhs: $1))})
|
||||
}
|
||||
}
|
||||
|
||||
// do
|
||||
|
||||
public func doOrDie<E>
|
||||
(eventHandler: (Event<E>) -> Result<Void>)
|
||||
-> (Observable<E> -> Observable<E>) {
|
||||
return { source in
|
||||
return Do(source: source, eventHandler: eventHandler)
|
||||
}
|
||||
}
|
||||
|
||||
public func `do`<E>
|
||||
(eventHandler: (Event<E>) -> Void)
|
||||
-> (Observable<E> -> Observable<E>) {
|
||||
return { source in
|
||||
return Do(source: source, eventHandler: { success(eventHandler($0)) })
|
||||
}
|
||||
}
|
||||
|
||||
// map aka select
|
||||
|
||||
public func mapOrDie<E, R>
|
||||
(selector: E -> Result<R>)
|
||||
-> (Observable<E> -> Observable<R>) {
|
||||
return { source in
|
||||
return selectOrDie(selector)(source)
|
||||
}
|
||||
}
|
||||
|
||||
public func map<E, R>
|
||||
(selector: E -> R)
|
||||
-> (Observable<E> -> Observable<R>) {
|
||||
return { source in
|
||||
return select(selector)(source)
|
||||
}
|
||||
}
|
||||
|
||||
public func mapWithIndexOrDie<E, R>
|
||||
(selector: (E, Int) -> Result<R>)
|
||||
-> (Observable<E> -> Observable<R>) {
|
||||
return { source in
|
||||
return selectWithIndexOrDie(selector)(source)
|
||||
}
|
||||
}
|
||||
|
||||
public func mapWithIndex<E, R>
|
||||
(selector: (E, Int) -> R)
|
||||
-> (Observable<E> -> Observable<R>) {
|
||||
return { source in
|
||||
return selectWithIndex(selector)(source)
|
||||
}
|
||||
}
|
||||
|
||||
// select
|
||||
|
||||
public func selectOrDie<E, R>
|
||||
(selector: (E) -> Result<R>)
|
||||
-> (Observable<E> -> Observable<R>) {
|
||||
return { source in
|
||||
return Select(source: source, selector: selector)
|
||||
}
|
||||
}
|
||||
|
||||
public func select<E, R>
|
||||
(selector: (E) -> R)
|
||||
-> (Observable<E> -> Observable<R>) {
|
||||
return { source in
|
||||
return Select(source: source, selector: {success(selector($0)) })
|
||||
}
|
||||
}
|
||||
|
||||
public func selectWithIndexOrDie<E, R>
|
||||
(selector: (E, Int) -> Result<R>)
|
||||
-> (Observable<E> -> Observable<R>) {
|
||||
return { source in
|
||||
return Select(source: source, selector: selector)
|
||||
}
|
||||
}
|
||||
|
||||
public func selectWithIndex<E, R>
|
||||
(selector: (E, Int) -> R)
|
||||
-> (Observable<E> -> Observable<R>) {
|
||||
return { source in
|
||||
return Select(source: source, selector: {success(selector($0, $1)) })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// Observable+StandardSequenceOperators.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/17/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
// filter aka where
|
||||
|
||||
public func filterOrDie<E>
|
||||
(predicate: (E) -> Result<Bool>)
|
||||
-> (Observable<E> -> Observable<E>) {
|
||||
return { source in
|
||||
return whereOrDie(predicate)(source)
|
||||
}
|
||||
}
|
||||
|
||||
public func filter<E>
|
||||
(predicate: (E) -> Bool)
|
||||
-> (Observable<E> -> Observable<E>) {
|
||||
return { source in
|
||||
return `where`(predicate)(source)
|
||||
}
|
||||
}
|
||||
|
||||
public func whereOrDie<E>
|
||||
(predicate: (E) -> Result<Bool>)
|
||||
-> (Observable<E> -> Observable<E>) {
|
||||
return { source in
|
||||
return WhereObservable(source: source, predicate: predicate)
|
||||
}
|
||||
}
|
||||
|
||||
public func `where`<E>
|
||||
(predicate: (E) -> Bool)
|
||||
-> (Observable<E> -> Observable<E>) {
|
||||
return { source in
|
||||
return WhereObservable(source: source, predicate: { success(predicate($0)) })
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
//
|
||||
// Observable+Time.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/22/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
// throttle
|
||||
|
||||
public func throttle<E, S: Scheduler>
|
||||
(dueTime: S.TimeInterval, scheduler: S)
|
||||
-> (Observable<E> -> Observable<E>) {
|
||||
return { source in
|
||||
return Throttle(source: source, dueTime: dueTime, scheduler: scheduler)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
//
|
||||
// ObserverOf.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/28/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct ObserverOf<ElementType> : ObserverType {
|
||||
typealias Element = ElementType
|
||||
|
||||
private typealias ObserverSinkType = (Event<Element>) -> Result<Void>
|
||||
|
||||
private let observer: ObserverSinkType
|
||||
private let instance: AnyObject?
|
||||
|
||||
/// Construct an instance whose `on(event)` calls `observer.on(event)`
|
||||
public init<O : ObserverClassType where O.Element == Element>(_ observer: O) {
|
||||
var observerReference = observer // this is because swift compiler crashing
|
||||
self.instance = observerReference
|
||||
self.observer = { e in
|
||||
return observerReference.on(e)
|
||||
}
|
||||
}
|
||||
|
||||
func ofType<T>() -> T? {
|
||||
return self.instance as? T
|
||||
}
|
||||
|
||||
/// Send `event` to this observer.
|
||||
public func on(event: Event<Element>) -> Result<Void> {
|
||||
return observer(event)
|
||||
}
|
||||
}
|
||||
|
||||
public func dispatch<Element>(event: Event<Element>, observers: [ObserverOf<Element>]?) -> Result<Void> {
|
||||
if let observers = observers {
|
||||
let results = observers.map { $0.on(event) }
|
||||
let result = doAll(results)
|
||||
return result
|
||||
}
|
||||
else {
|
||||
return SuccessResult
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// ObserverType.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/8/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol ObserverClassType : class, ObserverType {
|
||||
|
||||
}
|
||||
|
||||
public protocol ObserverType {
|
||||
/// The type of event to be written to this observer.
|
||||
typealias Element
|
||||
|
||||
/// Send `event` to this observer.
|
||||
mutating func on(event: Event<Element>) -> Result<Void>
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// AnonymousObserver.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/8/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class AnonymousObserver<ElementType> : ObserverClassType {
|
||||
typealias Element = ElementType
|
||||
|
||||
typealias EventHandler = Event<Element> -> Result<Void>
|
||||
|
||||
private let eventHandler : EventHandler
|
||||
|
||||
public init(_ eventHandler: EventHandler) {
|
||||
self.eventHandler = eventHandler
|
||||
}
|
||||
|
||||
public func on(event: Event<Element>) -> Result<Void> {
|
||||
return self.eventHandler(event)
|
||||
}
|
||||
|
||||
func makeSafe(disposable: Disposable) -> AnonymousSafeObserver<Element> {
|
||||
return AnonymousSafeObserver(eventHandler: eventHandler, disposable: disposable)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
//
|
||||
// AnonymousSafeObserver.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/21/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class AnonymousSafeObserver<ElementType> : ObserverClassType {
|
||||
typealias Element = ElementType
|
||||
|
||||
typealias State = Bool
|
||||
typealias EventHandler = Event<Element> -> Result<Void>
|
||||
|
||||
let eventHandler: EventHandler
|
||||
let disposable: Disposable
|
||||
|
||||
var lock = Lock()
|
||||
var stopped: State = false
|
||||
|
||||
init(eventHandler: EventHandler, disposable: Disposable) {
|
||||
self.eventHandler = eventHandler
|
||||
self.disposable = disposable
|
||||
}
|
||||
|
||||
func on(event: Event<Element>) -> Result<Void> {
|
||||
switch event {
|
||||
case .Next(let next):
|
||||
// TODO: in general case where next values could come from any thread
|
||||
// this is direct port from Rx
|
||||
// this looks like wrong logic, but for most cases this will work
|
||||
if stopped {
|
||||
return SuccessResult
|
||||
}
|
||||
|
||||
let nextResult = eventHandler(event)
|
||||
|
||||
return nextResult >>! { e in
|
||||
self.disposable.dispose()
|
||||
return .Error(e)
|
||||
}
|
||||
case .Error: fallthrough
|
||||
case .Completed:
|
||||
var stopped: Bool = lock.calculateLocked {
|
||||
var stopped = self.stopped;
|
||||
self.stopped = true;
|
||||
return stopped
|
||||
}
|
||||
|
||||
if !stopped {
|
||||
let result = self.eventHandler(event)
|
||||
self.disposable.dispose()
|
||||
return result
|
||||
}
|
||||
|
||||
return SuccessResult
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
//
|
||||
// AutoDetachObserver.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/15/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class AutoDetachObserver<Element> : ObserverBase<Element> {
|
||||
private let observer : ObserverOf<Element>
|
||||
private let m : SingleAssignmentDisposable
|
||||
|
||||
init(observer: ObserverOf<Element>) {
|
||||
self.observer = observer
|
||||
self.m = SingleAssignmentDisposable()
|
||||
|
||||
super.init()
|
||||
}
|
||||
|
||||
func setDisposable(disposable: Disposable) {
|
||||
m.setDisposable(disposable)
|
||||
}
|
||||
|
||||
override func onCore(event: Event<Element>) -> Result<Void> {
|
||||
switch event {
|
||||
case .Next:
|
||||
|
||||
return observer.on(event) >>! { e in
|
||||
self.dispose()
|
||||
return .Error(e)
|
||||
}
|
||||
|
||||
case .Completed: fallthrough
|
||||
case .Error:
|
||||
let result = observer.on(event)
|
||||
dispose()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
override func dispose() {
|
||||
super.dispose()
|
||||
m.dispose()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
//
|
||||
// DisposedObserver.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/21/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class DisposedObserver<ElementType> : ObserverType {
|
||||
typealias Element = ElementType
|
||||
|
||||
//static let Instance = DisposedObserver<ValueType>()
|
||||
|
||||
func on(event: Event<Element>) -> Result<Void> {
|
||||
rxFatalError("Already disposed")
|
||||
return .Error(UnknownError)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
//
|
||||
// DoneObserver.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/21/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class DoneObserver<ElementType> : ObserverType {
|
||||
typealias Element = ElementType
|
||||
|
||||
//static let Instance = DoneObserver<ValueType, ErrorType>()
|
||||
|
||||
func on(event: Event<Element>) -> Result<Void> {
|
||||
return SuccessResult
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
// NopObserver.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/21/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class NopObserver<ElementType> : ObserverClassType {
|
||||
typealias Element = ElementType
|
||||
//static let Instance = NopObserver<ValueType, ErrorType>()
|
||||
|
||||
func on(event: Event<Element>) -> Result<Void> {
|
||||
return SuccessResult
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
//
|
||||
// ObserverBase.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/15/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class ObserverBase<ElementType> : ObserverClassType, Disposable {
|
||||
typealias Element = ElementType
|
||||
|
||||
var lock = Lock()
|
||||
var isStopped: Bool = false
|
||||
|
||||
public init() {
|
||||
}
|
||||
|
||||
public func on(event: Event<Element>) -> Result<Void> {
|
||||
switch event {
|
||||
case .Next:
|
||||
if !isStopped {
|
||||
return onCore(event)
|
||||
}
|
||||
else {
|
||||
return SuccessResult
|
||||
}
|
||||
//return abstractMethod()
|
||||
case .Error: fallthrough
|
||||
case .Completed:
|
||||
var wasStopped: Bool = lock.calculateLocked {
|
||||
var wasStopped = self.isStopped
|
||||
self.isStopped = true
|
||||
return wasStopped
|
||||
}
|
||||
|
||||
if !wasStopped {
|
||||
return self.onCore(event)
|
||||
}
|
||||
return SuccessResult
|
||||
}
|
||||
}
|
||||
|
||||
public func onCore(event: Event<Element>) -> Result<Void> {
|
||||
return SuccessResult
|
||||
}
|
||||
|
||||
func fail(error: ErrorType) -> Result<Bool> {
|
||||
var wasStopped: Bool = lock.calculateLocked {
|
||||
var wasStopped = self.isStopped
|
||||
self.isStopped = true
|
||||
return wasStopped
|
||||
}
|
||||
|
||||
if !wasStopped {
|
||||
return self.onCore(.Error(error)) >>> {
|
||||
success(true)
|
||||
}
|
||||
}
|
||||
else {
|
||||
return success(false)
|
||||
}
|
||||
}
|
||||
|
||||
public func dispose() {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
//
|
||||
// SafeObserver.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/21/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class SafeObserver<ElementType> : ObserverClassType {
|
||||
typealias Element = ElementType
|
||||
|
||||
let observer: ObserverOf<Element>
|
||||
let disposable: Disposable
|
||||
|
||||
class func create(observer: ObserverOf<Element>, disposable: Disposable) -> ObserverOf<Element> {
|
||||
if let anonymousObserver: AnonymousObserver<Element> = observer.ofType() {
|
||||
let anonymousSafeObserver: AnonymousSafeObserver<Element> = anonymousObserver.makeSafe(disposable)
|
||||
return ObserverOf(anonymousSafeObserver)
|
||||
}
|
||||
else {
|
||||
let safeObserver: SafeObserver<Element> = SafeObserver<Element>(observer: observer, disposable: disposable)
|
||||
return ObserverOf(safeObserver)
|
||||
}
|
||||
}
|
||||
|
||||
init(observer: ObserverOf<Element>, disposable: Disposable) {
|
||||
self.observer = observer
|
||||
self.disposable = disposable
|
||||
#if DEBUG
|
||||
OSAtomicIncrement32(&resourceCount)
|
||||
#endif
|
||||
}
|
||||
|
||||
func on(event: Event<Element>) -> Result<Void> {
|
||||
switch event {
|
||||
case .Next:
|
||||
return self.observer.on(event) >>! { e in
|
||||
self.disposable.dispose()
|
||||
return .Error(e)
|
||||
}
|
||||
case .Completed: fallthrough
|
||||
case .Error:
|
||||
let result = self.observer.on(event)
|
||||
self.disposable.dispose()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
#if DEBUG
|
||||
OSAtomicDecrement32(&resourceCount)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,205 @@
|
|||
//
|
||||
// Result.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.
|
||||
//
|
||||
// Result is a `Either` Haskell monad.
|
||||
// The name `Result` was chosen because it better describes it's common usage.
|
||||
//
|
||||
public enum Result<ResultType> {
|
||||
// Box is used is because swift compiler doesn't know
|
||||
// how to handle `Success(ResultType)` and it crashes.
|
||||
case Success(Box<ResultType>)
|
||||
case Error(ErrorType)
|
||||
|
||||
init(_ value: ResultType) {
|
||||
self = .Success(Box(value))
|
||||
}
|
||||
|
||||
init(_ error: ErrorType) {
|
||||
self = .Error(error)
|
||||
}
|
||||
|
||||
public var error: ErrorType? {
|
||||
get {
|
||||
switch self {
|
||||
case .Error(let error): return error
|
||||
default: return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var value : ResultType? {
|
||||
get {
|
||||
switch self {
|
||||
case .Success(let value): return value.value
|
||||
default: return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public let SuccessResult = success(())
|
||||
|
||||
// Monad implementation for Result
|
||||
|
||||
// Monadic `return` implementation
|
||||
//
|
||||
// Naming clash with `return` keyword, `Success` function is more practical replacement.
|
||||
public func `return`<T>(value: T) -> Result<T> {
|
||||
return .Success(Box(value))
|
||||
}
|
||||
|
||||
// Monadic `bind` implementation
|
||||
//
|
||||
// `>==` is being used because `>>=` is already reserved operator in Swift.
|
||||
infix operator >== { associativity left precedence 95 }
|
||||
|
||||
public func >== <In, Out>(lhs: Result<In>, @noescape rhs: (In) -> Result<Out>) -> Result<Out> {
|
||||
switch lhs {
|
||||
case .Success(let result): return rhs(result.value)
|
||||
case .Error(let error): return .Error(error)
|
||||
}
|
||||
}
|
||||
|
||||
public func >== <In, Out>(lhs: Result<In>, @noescape rhs: (In) -> Out) -> Result<Out> {
|
||||
switch lhs {
|
||||
case .Success(let result): return success(rhs(result.value))
|
||||
case .Error(let error): return .Error(error)
|
||||
}
|
||||
}
|
||||
|
||||
// Control flow operators for `Result`
|
||||
|
||||
// In case `lhs` succeeded, result equals `rhs()`
|
||||
// In case `lhs` failed, just propagates failure
|
||||
infix operator >>> { associativity left precedence 95 }
|
||||
|
||||
public func >>> <In, Out>(lhs: Result<In>, @noescape rhs: () -> Out) -> Result<Out> {
|
||||
switch lhs {
|
||||
case .Success: return success(rhs())
|
||||
case .Error(let error): return .Error(error)
|
||||
}
|
||||
}
|
||||
|
||||
public func >>> <In, Out>(lhs: Result<In>, @noescape rhs: () -> Result<Out>) -> Result<Out> {
|
||||
switch lhs {
|
||||
case .Success: return rhs()
|
||||
case .Error(let error): return .Error(error)
|
||||
}
|
||||
}
|
||||
|
||||
// catch / fail operator
|
||||
//
|
||||
// In case `lhs` succeeded, result is propagated
|
||||
// In case `lhs` failed, result is equal to `rhs(error)` (catch clause) result
|
||||
infix operator >>! { associativity left precedence 95 }
|
||||
|
||||
public func >>! <In>(lhs: Result<In>, @noescape rhs: (ErrorType) -> Result<In>) -> Result<In> {
|
||||
switch lhs {
|
||||
case .Error(let error):
|
||||
return rhs(error)
|
||||
default:
|
||||
return lhs
|
||||
}
|
||||
}
|
||||
|
||||
// This shouldn't be a common operator to use (although it does come in handy sometime)
|
||||
//
|
||||
// In case `Result` contains value it will return value, otherwise it will throw an exception
|
||||
// This should only be used when the result is already checked for failure
|
||||
//
|
||||
// `>==` operator or lift functions are preferred.
|
||||
//
|
||||
prefix operator * { }
|
||||
public prefix func *<T>(result: Result<T>) -> T {
|
||||
switch result {
|
||||
case .Success(let value): return value.value
|
||||
default:
|
||||
var result: T? = nil
|
||||
return result!
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience constructor
|
||||
public func success<T>(value: T) -> Result<T> {
|
||||
return .Success(Box(value))
|
||||
}
|
||||
|
||||
// aggregate `Result` functions
|
||||
|
||||
public func doAll(results: [Result<Void>]) -> Result<Void> {
|
||||
var failures = results.filter { $0.error != nil }
|
||||
if failures.count > 0 {
|
||||
return createCompositeFailure(failures)
|
||||
}
|
||||
else {
|
||||
return SuccessResult
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// lift functions
|
||||
|
||||
// "Lifts" functions that take normal arguments to functions that take `Result` monad arguments.
|
||||
// Unfortunatelly 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) -> (Result<T1>) -> Result<TRet> {
|
||||
return { arg1 in
|
||||
return arg1 >== { value1 in
|
||||
return success(function(value1))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func lift<T1, T2, TRet>(function: (T1, T2) -> TRet) -> (Result<T1>, Result<T2>) -> Result<TRet> {
|
||||
return { arg1, arg2 in
|
||||
return arg1 >== { value1 in
|
||||
return arg2 >== { value2 in
|
||||
return success(function(value1, value2))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func lift<T1, T2, T3, TRet>(function: (T1, T2, T3) -> TRet) -> (Result<T1>, Result<T2>, Result<T3>) -> Result<TRet> {
|
||||
return { arg1, arg2, arg3 in
|
||||
return arg1 >== { value1 in
|
||||
return arg2 >== { value2 in
|
||||
return arg3 >== { value3 in
|
||||
return success(function(value1, value2, value3))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// error conversion functions
|
||||
|
||||
public func replaceErrorWith<T>(result: Result<T>, errorValue: T) -> T {
|
||||
switch result {
|
||||
case .Success(let boxedValue):
|
||||
return boxedValue.value
|
||||
case .Error:
|
||||
return errorValue
|
||||
}
|
||||
}
|
||||
|
||||
public func replaceErrorWithNil<T>(result: Result<T>) -> T? {
|
||||
switch result {
|
||||
case .Success(let boxedValue):
|
||||
return boxedValue.value
|
||||
case .Error:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
//
|
||||
// Rx.pch
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/12/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef Rx_Rx_pch
|
||||
#define Rx_Rx_pch
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
//
|
||||
// Rx.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/14/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
#if DEBUG
|
||||
// counts resources
|
||||
// used to detect resource leaks during unit tests
|
||||
// it's not perfect, but works well
|
||||
public var resourceCount: Int32 = 0
|
||||
#endif
|
||||
|
||||
// This is the pipline operator
|
||||
// a >- b >- c == c(b(a))
|
||||
// The reason this one is chosen for now is because
|
||||
// * It's subtle, doesn't add a lot of visual noise
|
||||
// * It's short
|
||||
// * It kind of looks like ASCII art horizontal sink to the right
|
||||
//
|
||||
infix operator >- { associativity left precedence 91 }
|
||||
|
||||
public func >- <In, Out>(source: In, @noescape transform: In -> Out) -> Out {
|
||||
return transform(source)
|
||||
}
|
||||
|
||||
func contract(@autoclosure condition: () -> Bool) {
|
||||
if !condition() {
|
||||
let exception = NSException(name: "ContractError", reason: "Contract failed", userInfo: nil)
|
||||
exception.raise()
|
||||
}
|
||||
}
|
||||
|
||||
// Because ... Swift
|
||||
// Because ... Crash
|
||||
// Because ... compiler bugs
|
||||
|
||||
// Wrapper for any value type
|
||||
public class Box<T> {
|
||||
public let value : T
|
||||
public init (_ value: T) {
|
||||
self.value = value
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapper for any value type that can be mutated
|
||||
public class MutatingBox<T> {
|
||||
public var value : T
|
||||
public init (_ value: T) {
|
||||
self.value = value
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
func abstractMethod<T>() -> T {
|
||||
rxFatalError("Abstract method")
|
||||
let dummyValue: T? = nil
|
||||
return dummyValue!
|
||||
}
|
||||
|
||||
func rxFatalError(lastMessage: String) {
|
||||
// The temptation to comment this line is great, but please don't, it's for your own good. The choice is yours.
|
||||
fatalError(lastMessage)
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
//
|
||||
// Scheduler.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/8/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol ImmediateScheduler {
|
||||
func schedule<StateType>(state: StateType, action: (StateType) -> Result<Void>) -> Result<Disposable>
|
||||
}
|
||||
|
||||
public protocol Scheduler: ImmediateScheduler {
|
||||
typealias TimeInterval
|
||||
typealias Time
|
||||
|
||||
var now : Time {
|
||||
get
|
||||
}
|
||||
|
||||
func schedule<StateType>(state: StateType, dueTime: TimeInterval, action: (StateType) -> Result<Void>) -> Result<Disposable>
|
||||
}
|
||||
|
||||
|
||||
// This is being called every time `Rx` scheduler performs action to
|
||||
// check the result of the computation.
|
||||
//
|
||||
// The default implementation will throw an Exception if the result failed.
|
||||
//
|
||||
// It's probably best to make sure all of the errors have been handled before
|
||||
// the computation finishes, but it's not unreasonable to change the implementation
|
||||
// for release builds to silently fail (although I would not recommended).
|
||||
//
|
||||
// Changing default behavior is not recommended because possible data corruption
|
||||
// is "usually" a lot worse then letting program to crash.
|
||||
//
|
||||
func ensureScheduledSuccessfully(result: Result<Void>) -> Result<Void> {
|
||||
switch result {
|
||||
case .Error(let error):
|
||||
return errorDuringScheduledAction(error);
|
||||
default: break
|
||||
}
|
||||
|
||||
return SuccessResult
|
||||
}
|
||||
|
||||
func errorDuringScheduledAction(error: ErrorType) -> Result<Void> {
|
||||
let exception = NSException(name: "ScheduledActionError", reason: "Error happened during scheduled action execution", userInfo: ["error": error])
|
||||
exception.raise()
|
||||
|
||||
return SuccessResult
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
//
|
||||
// DispatchQueueScheduler.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/8/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class DispatchQueueScheduler : Scheduler {
|
||||
public typealias Time = NSDate
|
||||
public typealias TimeInterval = NSTimeInterval
|
||||
|
||||
private let queue : dispatch_queue_t
|
||||
|
||||
public init(queue: dispatch_queue_t) {
|
||||
self.queue = queue
|
||||
|
||||
}
|
||||
|
||||
// DISPATCH_QUEUE_PRIORITY_DEFAULT
|
||||
// DISPATCH_QUEUE_PRIORITY_HIGH
|
||||
// DISPATCH_QUEUE_PRIORITY_LOW
|
||||
convenience public init(priority: Int) {
|
||||
self.init(queue: dispatch_get_global_queue(priority, UInt(0)))
|
||||
}
|
||||
|
||||
public var now : NSDate {
|
||||
get {
|
||||
return NSDate()
|
||||
}
|
||||
}
|
||||
|
||||
class func convertTimeIntervalToDispatchTime(timeInterval: NSTimeInterval) -> dispatch_time_t {
|
||||
return dispatch_time(DISPATCH_TIME_NOW, Int64(timeInterval * Double(NSEC_PER_SEC) / 1000))
|
||||
}
|
||||
|
||||
public func schedule<StateType>(state: StateType, action: (StateType) -> Result<Void>) -> Result<Disposable> {
|
||||
dispatch_async(self.queue, {
|
||||
ensureScheduledSuccessfully(action(state))
|
||||
})
|
||||
|
||||
return success(DefaultDisposable())
|
||||
}
|
||||
|
||||
public func schedule<StateType>(state: StateType, dueTime: NSTimeInterval, action: (StateType) -> Result<Void>) -> Result<Disposable> {
|
||||
let timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.queue)
|
||||
|
||||
let dispatchInterval = MainScheduler.convertTimeIntervalToDispatchTime(dueTime)
|
||||
|
||||
dispatch_source_set_timer(timer, dispatchInterval, DISPATCH_TIME_FOREVER, 0)
|
||||
dispatch_source_set_event_handler(timer, {
|
||||
ensureScheduledSuccessfully(action(state))
|
||||
})
|
||||
dispatch_resume(timer)
|
||||
|
||||
return success(AnonymousDisposable {
|
||||
dispatch_source_cancel(timer)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
//
|
||||
// ImmediateSchedulerOnCurrentThread.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/15/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct ImmediateSchedulerOnCurrentThread : ImmediateScheduler {
|
||||
public func schedule<StateType>(state: StateType, action: (StateType) -> Result<Void>) -> Result<Disposable> {
|
||||
return action(state) >>> { (DefaultDisposable()) }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// MainScheduler.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/8/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class MainScheduler : DispatchQueueScheduler {
|
||||
struct Singleton {
|
||||
static let sharedInstance = MainScheduler()
|
||||
}
|
||||
|
||||
init() {
|
||||
super.init(queue: dispatch_get_main_queue())
|
||||
}
|
||||
|
||||
public class var sharedInstance: MainScheduler {
|
||||
get {
|
||||
return Singleton.sharedInstance
|
||||
}
|
||||
}
|
||||
|
||||
public class func ensureExecutingOnScheduler() {
|
||||
if !NSThread.currentThread().isMainThread {
|
||||
rxFatalError("Executing on wrong scheduler")
|
||||
}
|
||||
}
|
||||
|
||||
public override func schedule<StateType>(state: StateType, action: (StateType) -> Result<Void>) -> Result<Disposable> {
|
||||
if NSThread.currentThread().isMainThread {
|
||||
ensureScheduledSuccessfully(action(state))
|
||||
|
||||
return success(DefaultDisposable())
|
||||
}
|
||||
|
||||
return super.schedule(state, action: action)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
// OperationQueueScheduler.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 4/4/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class OperationQueueScheduler: ImmediateScheduler {
|
||||
private let operationQueue: NSOperationQueue
|
||||
|
||||
public init(operationQueue: NSOperationQueue) {
|
||||
self.operationQueue = operationQueue
|
||||
}
|
||||
|
||||
public func schedule<StateType>(state: StateType, action: (StateType) -> Result<Void>) -> Result<Disposable> {
|
||||
let operation = NSBlockOperation {
|
||||
ensureScheduledSuccessfully(action(state))
|
||||
}
|
||||
self.operationQueue.addOperation(operation)
|
||||
|
||||
return success(AnonymousDisposable {
|
||||
operation.cancel()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
//
|
||||
// SchedulerDefaults.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/15/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct SchedulerDefaults {
|
||||
static var ConstantTimeOperations : ImmediateScheduler {
|
||||
get {
|
||||
return ImmediateSchedulerOnCurrentThread()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
//
|
||||
// ConnectableObservableType.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/1/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class ConnectableObservableType<Element>: Observable<Element> {
|
||||
public func connect() -> Result<Disposable> {
|
||||
return abstractMethod()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
//
|
||||
// SubjectType.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/1/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class SubjectType<SourceType, ResultType> : Observable<ResultType>, ObserverClassType {
|
||||
typealias Element = SourceType
|
||||
|
||||
public func on(x: Event<Element>) -> Result<Void> {
|
||||
return abstractMethod()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>Krunoslav-Zaher.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// ColdObservable.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/14/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Rx
|
||||
|
||||
class ColdObservable<Element: Equatable>: Observable<Element> {
|
||||
typealias Events = Recorded<Element>
|
||||
typealias ObserverType = ObserverOf<Element>
|
||||
|
||||
let testScheduler: TestScheduler
|
||||
|
||||
var subscriptions: [Subscription]
|
||||
var recordedEvents: [Events]
|
||||
var observers: Bag<ObserverOf<Element>>
|
||||
|
||||
init(testScheduler: TestScheduler, recordedEvents: [Events]) {
|
||||
self.testScheduler = testScheduler
|
||||
|
||||
self.recordedEvents = recordedEvents
|
||||
self.subscriptions = []
|
||||
self.observers = Bag()
|
||||
|
||||
super.init()
|
||||
}
|
||||
|
||||
override func subscribe(observer: ObserverOf<Element>) -> Result<Disposable> {
|
||||
let key = observers.put(observer)
|
||||
subscriptions.append(Subscription(subscribe: self.testScheduler.now))
|
||||
|
||||
let i = self.subscriptions.count - 1
|
||||
|
||||
for recordedEvent in recordedEvents {
|
||||
testScheduler.scheduleRelative((), after: recordedEvent.time, action: { (Int) in
|
||||
return doAll(self.observers.all.map { o in o.on(recordedEvent.event) })
|
||||
})
|
||||
}
|
||||
|
||||
return success(AnonymousDisposable {
|
||||
let removed = self.observers.removeKey(key)
|
||||
assert(removed != nil);
|
||||
|
||||
let existing = self.subscriptions[i]
|
||||
self.subscriptions[i] = Subscription(existing.subscribe, self.testScheduler.now)
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
//
|
||||
// HotObservable.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/14/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Rx
|
||||
|
||||
class HotObservable<Element : Equatable> : Observable<Element> {
|
||||
typealias Events = Recorded<Element>
|
||||
typealias ObserverType = ObserverOf<Element>
|
||||
|
||||
let testScheduler: TestScheduler
|
||||
|
||||
var subscriptions: [Subscription]
|
||||
var recordedEvents: [Events]
|
||||
var observers: Bag<ObserverOf<Element>>
|
||||
|
||||
init(testScheduler: TestScheduler, recordedEvents: [Events]) {
|
||||
self.testScheduler = testScheduler
|
||||
|
||||
self.recordedEvents = recordedEvents
|
||||
self.subscriptions = []
|
||||
self.observers = Bag()
|
||||
|
||||
super.init()
|
||||
|
||||
for recordedEvent in recordedEvents {
|
||||
testScheduler.schedule((), date: recordedEvent.time, action: { (Int) in
|
||||
return doAll(self.observers.all.map { o in o.on(recordedEvent.event) })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override func subscribe(observer: ObserverOf<Element>) -> Result<Disposable> {
|
||||
let key = observers.put(observer)
|
||||
subscriptions.append(Subscription(subscribe: self.testScheduler.now))
|
||||
|
||||
let i = self.subscriptions.count - 1
|
||||
|
||||
return success(AnonymousDisposable {
|
||||
let removed = self.observers.removeKey(key)
|
||||
assert(removed != nil)
|
||||
|
||||
let existing = self.subscriptions[i]
|
||||
self.subscriptions[i] = Subscription(existing.subscribe, self.testScheduler.now)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
public func == <T>(lhs: Observable<T>, rhs: Observable<T>) -> Bool {
|
||||
return lhs === rhs
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// MockObserver.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/15/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Rx
|
||||
|
||||
class MockObserver<ElementType : Equatable> : ObserverClassType {
|
||||
typealias Element = ElementType
|
||||
|
||||
let scheduler: TestScheduler
|
||||
var messages: [Recorded<Element>]
|
||||
|
||||
init(scheduler: TestScheduler) {
|
||||
self.scheduler = scheduler
|
||||
self.messages = []
|
||||
}
|
||||
|
||||
func on(event: Event<Element>) -> Result<Void> {
|
||||
messages.append(Recorded(time: scheduler.now, event: event))
|
||||
return SuccessResult
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
//
|
||||
// Observable.Extensions.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 3/14/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Rx
|
||||
|
||||
extension Observable : Equatable {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
//
|
||||
// TestObservable.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 2/14/15.
|
||||
// Copyright (c) 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Rx
|
||||
|
||||
/*protocol TestObservable : Observable {
|
||||
var subscriptions: [Subscription] { get }
|
||||
var recordedEvents: [Recorded<Element>] { get }
|
||||
}*/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue