Unit test pass and all of the bugs are fixed.

This commit is contained in:
Krunoslav Zaher 2015-04-08 00:28:38 +02:00
parent 7a5bb82ce4
commit f9d9c12a5c
182 changed files with 15275 additions and 414 deletions

View File

@ -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 */;
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:Example.xcodeproj">
</FileRef>
</Workspace>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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

9
LICENSE.md Normal file
View File

@ -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.

267
README.md Normal file
View File

@ -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)
}
```

View File

@ -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 */;
}

19
Rx.xcworkspace/contents.xcworkspacedata generated Normal file
View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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 */;
}

View File

@ -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>

View File

@ -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>

View File

@ -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>

27
Rx/Rx/AnyObject+Rx.swift Normal file
View File

@ -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
}

13
Rx/Rx/Cancelable.swift Normal file
View File

@ -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 }
}

View File

@ -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
}
}
}

View File

@ -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
}
}

View File

@ -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)
}
}

View File

@ -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
}
}

36
Rx/Rx/Disposable.swift Normal file
View File

@ -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)
}
}

View File

@ -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()
}
}
}

View File

@ -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()
}
}
}

View File

@ -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() {
}
}

View File

@ -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()
}
}

View File

@ -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
}
}

View File

@ -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()
}
}
}

View File

@ -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()
}
}
}

35
Rx/Rx/Error.swift Normal file
View File

@ -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)
}

71
Rx/Rx/Event.swift Normal file
View File

@ -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
}
}
}
}

View File

@ -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)
}

33
Rx/Rx/Observable.swift Normal file
View File

@ -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
}
}

View File

@ -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))
}
}

View File

@ -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)
}
}

View File

@ -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))
}
}

View File

@ -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()
}
}

View File

@ -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)
}
}

View File

@ -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
}
}
}

View File

@ -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)
}
}

View File

@ -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))
}
}

View File

@ -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))
}
}

View File

@ -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()
}
}
}

View File

@ -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()
}
}

View File

@ -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()
}
}

View File

@ -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()
}
}

View File

@ -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()
}
}

View File

@ -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()
}
}

View File

@ -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> {
}

View File

@ -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))
}
}

View File

@ -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
}
}

View File

@ -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")
}
}
}
}

View File

@ -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()
}
}

View File

@ -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()
}
}

View File

@ -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()
}
}

View File

@ -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)))
}

View File

@ -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)))
}
}

View File

@ -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) })
}
}

View File

@ -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)
}

View File

@ -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)
}
}

View File

@ -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()) }
}
}

View File

@ -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)
}
}

View File

@ -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)) })
}
}

View File

@ -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)) })
}
}

View File

@ -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)
}
}

47
Rx/Rx/ObserverOf.swift Normal file
View File

@ -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
}
}

21
Rx/Rx/ObserverType.swift Normal file
View File

@ -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>
}

View File

@ -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)
}
}

View File

@ -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
}
}
}

View File

@ -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()
}
}

View File

@ -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)
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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() {
}
}

View File

@ -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
}
}

205
Rx/Rx/Result.swift Normal file
View File

@ -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
}
}

View File

14
Rx/Rx/Rx.pch Normal file
View File

@ -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

69
Rx/Rx/Rx.swift Normal file
View File

@ -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)
}

54
Rx/Rx/Scheduler.swift Normal file
View File

@ -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
}

View File

@ -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)
})
}
}

View File

@ -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()) }
}
}

View File

@ -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)
}
}

View File

@ -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()
})
}
}

View File

@ -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()
}
}
}

View File

@ -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()
}
}

View File

@ -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()
}
}

24
Rx/RxTests/Info.plist Normal file
View File

@ -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>

View File

@ -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)
})
}
}

View File

@ -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
}

View File

@ -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
}
}

View File

@ -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 {
}

View File

@ -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