Compare commits
69 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c3b601df0f | |||
| 56b0768d60 | |||
| 8cf87efb95 | |||
| 3aa9b334f1 | |||
| b2a0cda242 | |||
| 07eb66e87d | |||
| 82e3d02497 | |||
| 3b2f5a272f | |||
| eab2d424e7 | |||
| 0f2cda0a52 | |||
| 05c02c9645 | |||
| fa086dad8f | |||
| cdc09f5a03 | |||
| b94ed3bea2 | |||
| 0fd70e65dd | |||
| 97e7f4782f | |||
| f1fdbbc988 | |||
| e368bb3051 | |||
| 4ce4832960 | |||
| d3bd0c27e3 | |||
| be0c39ab6b | |||
| 0de45e7d53 | |||
| 3b421d0cff | |||
| f1234bf2b9 | |||
| b0d7153bfe | |||
| 0193aa6bf6 | |||
| de7ad3ac48 | |||
| 40ad490c48 | |||
| 95cc5df26f | |||
| 09a7115aff | |||
| 15c0002ea3 | |||
| 0644d85a9c | |||
| e1522a0bf3 | |||
| a659415496 | |||
| efe25d575b | |||
| 22c67fa30c | |||
| 7a091da44d | |||
| 9580976dd8 | |||
| a4f0256313 | |||
| 815e9ccd66 | |||
| b9bf9c4d75 | |||
| 530a20999a | |||
| 4f3bc1e498 | |||
| 8dcb136ff0 | |||
| 88d02af706 | |||
| a8777c067e | |||
| db40e8580c | |||
| 334fb384a5 | |||
| 54e1db2232 | |||
| c5c6bd2821 | |||
| 593129c63e | |||
| 9a8d919a13 | |||
| 17a2d64361 | |||
| 27037c2dd7 | |||
| bd253f4b0a | |||
| 882b2a2031 | |||
| 6a14c1f96d | |||
| f60e322445 | |||
| 77f6fde2fa | |||
| a8f7a2972a | |||
| ce9088afc7 | |||
| ef563c65ba | |||
| 90ff39c720 | |||
| e45dbd634f | |||
| f81c267c61 | |||
| d5b07b1916 | |||
| 33993df68a | |||
| dadb68862a | |||
| 2e53aa8ae2 |
@@ -36,3 +36,4 @@ Carthage
|
||||
# SPM
|
||||
.build/
|
||||
Packages
|
||||
.swiftpm
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
4.1
|
||||
+29
-5
@@ -5,13 +5,25 @@ matrix:
|
||||
- script:
|
||||
- set -o pipefail && xcodebuild test -workspace Dip.xcworkspace -scheme Dip -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6,OS=latest' ONLY_ACTIVE_ARCH=NO | xcpretty -c
|
||||
- set -o pipefail && xcodebuild test -workspace Dip.xcworkspace -scheme Dip -sdk macosx -destination 'platform=macOS,arch=x86_64' ONLY_ACTIVE_ARCH=NO | xcpretty -c
|
||||
- pod spec lint --allow-warnings
|
||||
# - pod spec lint --allow-warnings
|
||||
- carthage build --no-skip-current
|
||||
- swift package clean && swift build && swift test
|
||||
os: osx
|
||||
osx_image: xcode9.3
|
||||
osx_image: xcode10.2
|
||||
language: objective-c
|
||||
before_install:
|
||||
- gem install cocoapods --version 1.1.0.rc.2 --no-document
|
||||
- gem install cocoapods --version 1.8.4 --no-document
|
||||
- script:
|
||||
- set -o pipefail && xcodebuild test -workspace Dip.xcworkspace -scheme Dip -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 11,OS=latest' ONLY_ACTIVE_ARCH=NO | xcpretty -c
|
||||
- set -o pipefail && xcodebuild test -workspace Dip.xcworkspace -scheme Dip -sdk macosx -destination 'platform=macOS,arch=x86_64' ONLY_ACTIVE_ARCH=NO | xcpretty -c
|
||||
# - pod spec lint --allow-warnings
|
||||
- carthage build --no-skip-current
|
||||
- swift package clean && swift build && swift test
|
||||
os: osx
|
||||
osx_image: xcode11.2
|
||||
language: objective-c
|
||||
before_install:
|
||||
- gem install cocoapods --version 1.8.4 --no-document
|
||||
- script:
|
||||
- swift package clean && swift build && swift test
|
||||
os: linux
|
||||
@@ -21,13 +33,25 @@ matrix:
|
||||
before_install:
|
||||
- wget -q -O - https://swift.org/keys/all-keys.asc | gpg --import -
|
||||
- cd ..
|
||||
- export SWIFT_VERSION=swift-4.1-RELEASE
|
||||
- wget https://swift.org/builds/swift-4.1-release/ubuntu1404/$SWIFT_VERSION/$SWIFT_VERSION-ubuntu14.04.tar.gz
|
||||
- export SWIFT_VERSION=swift-5.1-RELEASE
|
||||
- wget https://swift.org/builds/swift-5.1-release/ubuntu1404/$SWIFT_VERSION/$SWIFT_VERSION-ubuntu14.04.tar.gz
|
||||
- tar xzf $SWIFT_VERSION-ubuntu14.04.tar.gz
|
||||
- export PATH="${PWD}/${SWIFT_VERSION}-ubuntu14.04/usr/bin:${PATH}"
|
||||
- cd Dip
|
||||
- script:
|
||||
- swift package clean && swift build && swift test
|
||||
os: linux
|
||||
dist: trusty
|
||||
sudo: required
|
||||
language: generic
|
||||
before_install:
|
||||
- wget -q -O - https://swift.org/keys/all-keys.asc | gpg --import -
|
||||
- cd ..
|
||||
- export SWIFT_VERSION=swift-5.0-RELEASE
|
||||
- wget https://swift.org/builds/swift-5.0-release/ubuntu1404/$SWIFT_VERSION/$SWIFT_VERSION-ubuntu14.04.tar.gz
|
||||
- tar xzf $SWIFT_VERSION-ubuntu14.04.tar.gz
|
||||
- export PATH="${PWD}/${SWIFT_VERSION}-ubuntu14.04/usr/bin:${PATH}"
|
||||
- cd Dip
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
|
||||
+27
-2
@@ -1,9 +1,34 @@
|
||||
# CHANGELOG
|
||||
|
||||
## Develop
|
||||
|
||||
## 7.1.1
|
||||
|
||||
* Fixed using `StoryboardInstantiatable` with SPM ([#233](https://github.com/AliSoftware/Dip/pull/233)).
|
||||
|
||||
## 7.1.0
|
||||
|
||||
* You can now use a shorthand syntax for resolving a single property using a key path, i.e. `resolvingProperty(\.value)`.
|
||||
* Swift 5.0 support ([#224](https://github.com/AliSoftware/Dip/pull/224)).
|
||||
* Fixed resolving nested types with the same local names ([#221](https://github.com/AliSoftware/Dip/pull/221)).
|
||||
* `@Injected` and `@IntectedWeak` property wrappers ([#225](https://github.com/AliSoftware/Dip/pull/225)).
|
||||
* Thread safety can be disabled on container level.
|
||||
|
||||
## 7.0.1
|
||||
|
||||
* Added a workaround for Swift 4.2 regression related to retaining weak properties ([#214](https://github.com/AliSoftware/Dip/issues/214)).
|
||||
For that auto-injection can be disabled or enabled for the whole container or individula registrations.
|
||||
|
||||
## 7.0.0
|
||||
|
||||
* Swift 4.2 support.
|
||||
* Fixed some issues when reusing instances previously resolved as optionals.
|
||||
* Dip-UI is now part of Dip.
|
||||
|
||||
## 6.1
|
||||
|
||||
* Swift 4.1 support
|
||||
* Fixed crashes resolving singletons using collaborating containers
|
||||
* Swift 4.1 support.
|
||||
* Fixed crashes resolving singletons using collaborating containers.
|
||||
[#179](https://github.com/AliSoftware/Dip/pull/179), [@trimmurrti](https://github.com/trimmurrti)
|
||||
[#182](https://github.com/AliSoftware/Dip/pull/182), [@tapsandswipes](https://github.com/tapsandswipes)
|
||||
|
||||
|
||||
+4
-2
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "Dip"
|
||||
s.version = "6.1"
|
||||
s.version = "7.1.1"
|
||||
s.summary = "Dependency Injection for Swift made easy."
|
||||
|
||||
s.description = <<-DESC
|
||||
@@ -11,7 +11,7 @@ Pod::Spec.new do |s|
|
||||
|
||||
s.homepage = "https://github.com/AliSoftware/Dip"
|
||||
s.license = 'MIT'
|
||||
s.authors = { "Olivier Halligon" => "olivier@halligon.net", "Ilya Puchka" => "ilya@puchka.me" }
|
||||
s.authors = { "Olivier Halligon" => "olivier@halligon.net", "Ilya Puchka" => "ilyapuchka@gmail.com" }
|
||||
s.source = { :git => "https://github.com/AliSoftware/Dip.git", :tag => s.version.to_s }
|
||||
s.social_media_url = 'https://twitter.com/aligatr'
|
||||
|
||||
@@ -23,4 +23,6 @@ Pod::Spec.new do |s|
|
||||
s.requires_arc = true
|
||||
|
||||
s.source_files = 'Sources/**/*.swift'
|
||||
|
||||
s.swift_version = "5.0", "5.1"
|
||||
end
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
09FC480F1DAA9CAF00566AA8 /* Register.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09FC480C1DAA9CAF00566AA8 /* Register.swift */; };
|
||||
09FC48181DAAA53100566AA8 /* DipError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09FC48161DAAA53100566AA8 /* DipError.swift */; };
|
||||
09FC481E1DAAA8F900566AA8 /* ComponentScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09FC481C1DAAA8F900566AA8 /* ComponentScope.swift */; };
|
||||
63937A6A21524C0B00AEE75A /* StoryboardInstantiatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63937A6921524C0B00AEE75A /* StoryboardInstantiatable.swift */; };
|
||||
63937A6F21524DA300AEE75A /* DipUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63937A6B21524DA200AEE75A /* DipUITests.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@@ -71,6 +73,11 @@
|
||||
09FC480C1DAA9CAF00566AA8 /* Register.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Register.swift; path = ../../Sources/Register.swift; sourceTree = "<group>"; };
|
||||
09FC48161DAAA53100566AA8 /* DipError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DipError.swift; path = ../../Sources/DipError.swift; sourceTree = "<group>"; };
|
||||
09FC481C1DAAA8F900566AA8 /* ComponentScope.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ComponentScope.swift; path = ../../Sources/ComponentScope.swift; sourceTree = "<group>"; };
|
||||
63937A6921524C0B00AEE75A /* StoryboardInstantiatable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = StoryboardInstantiatable.swift; path = ../../Sources/StoryboardInstantiatable.swift; sourceTree = "<group>"; };
|
||||
63937A6B21524DA200AEE75A /* DipUITests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DipUITests.swift; path = ../../Tests/DipTests/DipUITests.swift; sourceTree = "<group>"; };
|
||||
63937A6C21524DA200AEE75A /* NSStoryboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NSStoryboard.storyboard; sourceTree = "<group>"; };
|
||||
63937A6D21524DA300AEE75A /* TVStoryboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = TVStoryboard.storyboard; sourceTree = "<group>"; };
|
||||
63937A6E21524DA300AEE75A /* UIStoryboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = UIStoryboard.storyboard; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -108,6 +115,7 @@
|
||||
095F829B1D043B41008CD706 /* TypeForwarding.swift */,
|
||||
0982AF0B1C5183A000B62463 /* Utils.swift */,
|
||||
09871B401DAA6BF300B40B91 /* Compatibility.swift */,
|
||||
63937A6921524C0B00AEE75A /* StoryboardInstantiatable.swift */,
|
||||
0919F4CB1C16417000DC3B10 /* Info.plist */,
|
||||
);
|
||||
path = Dip;
|
||||
@@ -125,6 +133,10 @@
|
||||
09BD350A1D84E30D00B33E53 /* RuntimeArgumentsTests.swift */,
|
||||
09BD350B1D84E30D00B33E53 /* ThreadSafetyTests.swift */,
|
||||
09BD350C1D84E30D00B33E53 /* TypeForwardingTests.swift */,
|
||||
63937A6B21524DA200AEE75A /* DipUITests.swift */,
|
||||
63937A6C21524DA200AEE75A /* NSStoryboard.storyboard */,
|
||||
63937A6D21524DA300AEE75A /* TVStoryboard.storyboard */,
|
||||
63937A6E21524DA300AEE75A /* UIStoryboard.storyboard */,
|
||||
09BD350D1D84E30D00B33E53 /* Utils.swift */,
|
||||
0919F4D11C16417000DC3B10 /* Info.plist */,
|
||||
);
|
||||
@@ -189,6 +201,7 @@
|
||||
buildPhases = (
|
||||
0903B35D1C161543002241C1 /* Sources */,
|
||||
0903B35E1C161543002241C1 /* Frameworks */,
|
||||
63937A7721524E3B00AEE75A /* ShellScript */,
|
||||
0903B35F1C161543002241C1 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
@@ -208,25 +221,26 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0730;
|
||||
LastUpgradeCheck = 0930;
|
||||
LastUpgradeCheck = 1020;
|
||||
ORGANIZATIONNAME = AliSoftware;
|
||||
TargetAttributes = {
|
||||
0903B3571C161543002241C1 = {
|
||||
CreatedOnToolsVersion = 7.1.1;
|
||||
LastSwiftMigration = 0800;
|
||||
LastSwiftMigration = 1020;
|
||||
};
|
||||
0903B3601C161543002241C1 = {
|
||||
CreatedOnToolsVersion = 7.1.1;
|
||||
LastSwiftMigration = 0800;
|
||||
LastSwiftMigration = 1020;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 0945268B1BEA1CFF0034E72A /* Build configuration list for PBXProject "Dip" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 094526871BEA1CFF0034E72A;
|
||||
productRefGroup = 094526921BEA1CFF0034E72A /* Products */;
|
||||
@@ -256,6 +270,26 @@
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
63937A7721524E3B00AEE75A /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "echo \"${SRCROOT}/DipTests/${STORYBOARD_NAME_PREFIX}Storyboard.storyboard\"\nibtool --compilation-directory \"${TARGET_TEMP_DIR}\" \"${SRCROOT}/DipTests/${STORYBOARD_NAME_PREFIX}Storyboard.storyboard\"\nibtool --link \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}\" \"${TARGET_TEMP_DIR}/${STORYBOARD_NAME_PREFIX}Storyboard.storyboardc\"\n";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
0903B3531C161543002241C1 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
@@ -265,6 +299,7 @@
|
||||
0982AF0C1C5183A000B62463 /* Utils.swift in Sources */,
|
||||
0919F4D51C16417B00DC3B10 /* Definition.swift in Sources */,
|
||||
09FC481E1DAAA8F900566AA8 /* ComponentScope.swift in Sources */,
|
||||
63937A6A21524C0B00AEE75A /* StoryboardInstantiatable.swift in Sources */,
|
||||
09B036001C5D2B83001EA5B7 /* AutoWiring.swift in Sources */,
|
||||
0919F4D41C16417B00DC3B10 /* Dip.swift in Sources */,
|
||||
09FC480F1DAA9CAF00566AA8 /* Register.swift in Sources */,
|
||||
@@ -282,6 +317,7 @@
|
||||
files = (
|
||||
09BD35141D84E30D00B33E53 /* RuntimeArgumentsTests.swift in Sources */,
|
||||
09BD35151D84E30D00B33E53 /* ThreadSafetyTests.swift in Sources */,
|
||||
63937A6F21524DA300AEE75A /* DipUITests.swift in Sources */,
|
||||
09BD35121D84E30D00B33E53 /* DefinitionTests.swift in Sources */,
|
||||
09BD350F1D84E30D00B33E53 /* AutoWiringTests.swift in Sources */,
|
||||
09BD35111D84E30D00B33E53 /* ContextTests.swift in Sources */,
|
||||
@@ -325,6 +361,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.alisoftware.Dip;
|
||||
PRODUCT_NAME = Dip;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -344,6 +381,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.alisoftware.Dip;
|
||||
PRODUCT_NAME = Dip;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@@ -359,7 +397,13 @@
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.alisoftware.DipTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
STORYBOARD_NAME_PREFIX = NS;
|
||||
"STORYBOARD_NAME_PREFIX[sdk=appletvos*]" = TV;
|
||||
"STORYBOARD_NAME_PREFIX[sdk=appletvsimulator*]" = TV;
|
||||
"STORYBOARD_NAME_PREFIX[sdk=iphoneos*]" = UI;
|
||||
"STORYBOARD_NAME_PREFIX[sdk=iphonesimulator*]" = UI;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -375,6 +419,8 @@
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.alisoftware.DipTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
STORYBOARD_NAME_PREFIX = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@@ -382,6 +428,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
@@ -407,7 +454,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 6.1;
|
||||
CURRENT_PROJECT_VERSION = 7.0.1;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
@@ -432,12 +479,12 @@
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SUPPORTED_PLATFORMS = "macosx watchsimulator iphonesimulator appletvsimulator watchos appletvos iphoneos";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 4.0;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2,3,4";
|
||||
TVOS_DEPLOYMENT_TARGET = 9.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
WATCHOS_DEPLOYMENT_TARGET = 2.0;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 3.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -445,6 +492,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
@@ -470,7 +518,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 6.1;
|
||||
CURRENT_PROJECT_VERSION = 7.0.1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
@@ -488,13 +536,13 @@
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SUPPORTED_PLATFORMS = "macosx watchsimulator iphonesimulator appletvsimulator watchos appletvos iphoneos";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SWIFT_VERSION = 4.0;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2,3,4";
|
||||
TVOS_DEPLOYMENT_TARGET = 9.0;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
WATCHOS_DEPLOYMENT_TARGET = 2.0;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 3.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0930"
|
||||
LastUpgradeVersion = "1020"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
@@ -40,7 +40,6 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
codeCoverageEnabled = "YES"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.1</string>
|
||||
<string>7.1.1</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.1</string>
|
||||
<string>7.1.1</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14313.18"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Dip View Controller-->
|
||||
<scene sceneID="adI-oe-5KL">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="DipViewController" id="fzZ-tH-vfC" customClass="DipViewController" customModule="DipTests" sceneMemberID="viewController">
|
||||
<view key="view" id="vso-jO-9Ex">
|
||||
<rect key="frame" x="0.0" y="0.0" width="450" height="300"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</view>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="dipTag" value="vc"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</viewController>
|
||||
<customObject id="wjM-mL-nmG" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="311" y="339"/>
|
||||
</scene>
|
||||
<!--Nil Tag View Controller-->
|
||||
<scene sceneID="OhX-tC-zpS">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="NilTagViewController" id="35S-Ec-qEA" customClass="NilTagViewController" customModule="DipTests" sceneMemberID="viewController">
|
||||
<view key="view" id="y58-K4-cDZ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="450" height="300"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</view>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="nil" keyPath="dipTag"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</viewController>
|
||||
<customObject id="pvf-jv-8Cj" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="874" y="339"/>
|
||||
</scene>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="Rwu-gt-fAa">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="ViewController" id="tne-ER-mvb" sceneMemberID="viewController">
|
||||
<view key="view" id="Kwe-OO-w0D">
|
||||
<rect key="frame" x="0.0" y="0.0" width="450" height="300"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<customObject id="0u1-hv-ZtW" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="311" y="729"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
@@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder.AppleTV.Storyboard" version="3.0" toolsVersion="14313.18" targetRuntime="AppleTV" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="ctX-Lj-Yrr">
|
||||
<device id="appleTV" orientation="landscape">
|
||||
<adaptation id="light"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Dip View Controller-->
|
||||
<scene sceneID="0jz-eb-APg">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="DipViewController" id="ctX-Lj-Yrr" customClass="DipViewController" customModule="DipTests" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="TrC-Rh-efi"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="arQ-XW-qWa"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="syn-UA-YGd">
|
||||
<rect key="frame" x="0.0" y="0.0" width="200" height="100"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
</view>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<size key="freeformSize" width="200" height="100"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="dipTag" value="vc"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="mq6-CB-g6V" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="563" y="-228"/>
|
||||
</scene>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="gDU-un-krd">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="ViewController" id="UwR-h2-tgS" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="qKG-R0-Nkp"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="vP4-Si-HAL"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="r35-FI-kgS">
|
||||
<rect key="frame" x="0.0" y="0.0" width="200" height="100"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
</view>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<size key="freeformSize" width="200" height="100"/>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="AIY-qB-Dbe" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="563" y="-16"/>
|
||||
</scene>
|
||||
<!--Nil Tag View Controller-->
|
||||
<scene sceneID="PiH-4i-Txa">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="NilTagViewController" id="ZLb-1s-1ne" customClass="NilTagViewController" customModule="DipTests" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="arU-Ca-km8"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="jw1-4B-Xlt"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="NMo-Oi-l7H">
|
||||
<rect key="frame" x="0.0" y="0.0" width="200" height="100"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
</view>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<size key="freeformSize" width="200" height="100"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="nil" keyPath="dipTag"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Cid-Yu-0N6" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="821" y="-228"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
@@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="5AO-J3-7R4">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="Ole-tM-Q3l">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="ViewController" id="ehZ-7Y-MeO" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="bZ0-tI-Yi9"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="UX3-8G-Z4L"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="Jmi-i3-vAY">
|
||||
<rect key="frame" x="0.0" y="0.0" width="200" height="100"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</view>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<size key="freeformSize" width="200" height="100"/>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="H12-WL-igv" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="646" y="461"/>
|
||||
</scene>
|
||||
<!--Dip View Controller-->
|
||||
<scene sceneID="Lgf-SY-hfd">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="DipViewController" id="5AO-J3-7R4" userLabel="Dip View Controller" customClass="DipViewController" customModule="DipTests" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="JYl-DM-U2W"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="Xg8-gz-BQL"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="aU0-uz-rHf">
|
||||
<rect key="frame" x="0.0" y="0.0" width="200" height="100"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</view>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<size key="freeformSize" width="200" height="100"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="dipTag" value="vc"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="4iF-mX-EX6" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="646" y="200"/>
|
||||
</scene>
|
||||
<!--Dip View Controller-->
|
||||
<scene sceneID="AUA-qF-7ky">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="NilTagViewController" id="fFP-hb-OdS" userLabel="Dip View Controller" customClass="NilTagViewController" customModule="DipTests" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="Sio-ii-jPl"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="bhs-zK-dln"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="4xq-UV-htt">
|
||||
<rect key="frame" x="0.0" y="0.0" width="200" height="100"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</view>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<size key="freeformSize" width="200" height="100"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="nil" keyPath="dipTag"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="xvW-k9-I9y" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="898" y="200"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
@@ -0,0 +1,76 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
CFPropertyList (3.0.0)
|
||||
activesupport (4.2.11)
|
||||
i18n (~> 0.7)
|
||||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.3, >= 0.3.4)
|
||||
tzinfo (~> 1.1)
|
||||
atomos (0.1.3)
|
||||
claide (1.0.2)
|
||||
cocoapods (1.4.0)
|
||||
activesupport (>= 4.0.2, < 5)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
cocoapods-core (= 1.4.0)
|
||||
cocoapods-deintegrate (>= 1.0.2, < 2.0)
|
||||
cocoapods-downloader (>= 1.1.3, < 2.0)
|
||||
cocoapods-plugins (>= 1.0.0, < 2.0)
|
||||
cocoapods-search (>= 1.0.0, < 2.0)
|
||||
cocoapods-stats (>= 1.0.0, < 2.0)
|
||||
cocoapods-trunk (>= 1.3.0, < 2.0)
|
||||
cocoapods-try (>= 1.1.0, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
escape (~> 0.0.4)
|
||||
fourflusher (~> 2.0.1)
|
||||
gh_inspector (~> 1.0)
|
||||
molinillo (~> 0.6.4)
|
||||
nap (~> 1.0)
|
||||
ruby-macho (~> 1.1)
|
||||
xcodeproj (>= 1.5.4, < 2.0)
|
||||
cocoapods-core (1.4.0)
|
||||
activesupport (>= 4.0.2, < 6)
|
||||
fuzzy_match (~> 2.0.4)
|
||||
nap (~> 1.0)
|
||||
cocoapods-deintegrate (1.0.2)
|
||||
cocoapods-downloader (1.2.2)
|
||||
cocoapods-plugins (1.0.0)
|
||||
nap
|
||||
cocoapods-search (1.0.0)
|
||||
cocoapods-stats (1.0.0)
|
||||
cocoapods-trunk (1.3.1)
|
||||
nap (>= 0.8, < 2.0)
|
||||
netrc (~> 0.11)
|
||||
cocoapods-try (1.1.0)
|
||||
colored2 (3.1.2)
|
||||
concurrent-ruby (1.1.4)
|
||||
escape (0.0.4)
|
||||
fourflusher (2.0.1)
|
||||
fuzzy_match (2.0.4)
|
||||
gh_inspector (1.1.3)
|
||||
i18n (0.9.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
minitest (5.11.3)
|
||||
molinillo (0.6.6)
|
||||
nanaimo (0.2.6)
|
||||
nap (1.1.0)
|
||||
netrc (0.11.0)
|
||||
ruby-macho (1.3.1)
|
||||
thread_safe (0.3.6)
|
||||
tzinfo (1.2.5)
|
||||
thread_safe (~> 0.1)
|
||||
xcodeproj (1.7.0)
|
||||
CFPropertyList (>= 2.3.3, < 4.0)
|
||||
atomos (~> 0.1.3)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
nanaimo (~> 0.2.6)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
cocoapods (= 1.4.0)
|
||||
|
||||
BUNDLED WITH
|
||||
1.16.5
|
||||
@@ -0,0 +1,8 @@
|
||||
import XCTest
|
||||
|
||||
import DipTests
|
||||
|
||||
var tests = [XCTestCaseEntry]()
|
||||
tests += DipTests.__allTests()
|
||||
|
||||
XCTMain(tests)
|
||||
+9
-24
@@ -1,30 +1,15 @@
|
||||
//
|
||||
// Dip
|
||||
//
|
||||
// Copyright (c) 2015 Olivier Halligon <olivier@halligon.net>
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// swift-tools-version:5.0
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "Dip"
|
||||
name: "Dip",
|
||||
products: [
|
||||
.library(name: "Dip", targets: ["Dip"]),
|
||||
],
|
||||
targets: [
|
||||
.target(name: "Dip", dependencies: [], path: "Sources"),
|
||||
.testTarget(name: "DipTests", dependencies: ["Dip"], path: "Tests"),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
[](https://github.com/Carthage/Carthage)
|
||||
[](http://cocoapods.org/pods/Dip)
|
||||
[](http://cocoapods.org/pods/Dip)
|
||||
[](https://developer.apple.com/swift)
|
||||
[](https://developer.apple.com/swift)
|
||||
[](https://developer.apple.com/swift)
|
||||
[](https://developer.apple.com/swift)
|
||||
|
||||

|
||||
_Photo courtesy of [www.kevinandamanda.com](http://www.kevinandamanda.com/recipes/appetizer/homemade-soft-cinnamon-sugar-pretzel-bites-with-salted-caramel-dipping-sauce.html)_
|
||||
@@ -19,7 +19,7 @@ It's aimed to be as simple as possible yet provide rich functionality usual for
|
||||
|
||||
* You start by creating `let container = DependencyContainer()` and **registering your dependencies, by associating a _protocol_ or _type_ to a `factory`** using `container.register { MyService() as Service }`.
|
||||
* Then you can call `container.resolve() as Service` to **resolve an instance of _protocol_ or _type_** using that `DependencyContainer`.
|
||||
* You can easily use Dip along with **Storyboards and Nibs** - checkout **[Dip-UI](https://github.com/AliSoftware/Dip-UI)** extensions. There is also a **[code generator](https://github.com/ilyapuchka/dipgen)** that can help to simplify registering new components.
|
||||
* You can easily use Dip along with **Storyboards and Nibs** . There is also a **[code generator](https://github.com/ilyapuchka/dipgen)** that can help to simplify registering new components.
|
||||
|
||||
<details>
|
||||
<summary>Basic usage</summary>
|
||||
@@ -148,27 +148,13 @@ File an issue if you have any question. Pull requests are warmly welcome too.
|
||||
|
||||
## Installation
|
||||
|
||||
Since version 5.0.0 Dip is built with Swift 3.0. You can install Dip using your favorite dependency manager:
|
||||
You can install Dip using your favorite dependency manager:
|
||||
|
||||
<details>
|
||||
<summary>CocoaPods</summary>
|
||||
|
||||
`pod "Dip"`
|
||||
|
||||
To build for Swift 2.3 add this code to the bottom of your Podfile
|
||||
|
||||
```ruby
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
target.build_configurations.each do |config|
|
||||
config.build_settings['SWIFT_VERSION'] = '2.3'
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
> You need at least 1.1.0.rc.2 version of CocoaPods.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
@@ -279,7 +279,7 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0700;
|
||||
LastUpgradeCheck = 0930;
|
||||
LastUpgradeCheck = 1020;
|
||||
ORGANIZATIONNAME = AliSoftware;
|
||||
TargetAttributes = {
|
||||
0990225E1BC123C000E76F43 = {
|
||||
@@ -292,7 +292,7 @@
|
||||
};
|
||||
buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "DipSampleApp" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
@@ -423,6 +423,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
@@ -479,6 +480,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0930"
|
||||
LastUpgradeVersion = "1020"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.1</string>
|
||||
<string>7.1.1</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.1</string>
|
||||
<string>7.1.1</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
|
||||
+205
-81
@@ -78,7 +78,7 @@ extension DependencyContainer {
|
||||
```
|
||||
|
||||
*/
|
||||
public protocol AutoInjectedPropertyBox: class {
|
||||
public protocol AutoInjectedPropertyBox {
|
||||
///The type of wrapped property.
|
||||
static var wrappedType: Any.Type { get }
|
||||
|
||||
@@ -93,40 +93,108 @@ public protocol AutoInjectedPropertyBox: class {
|
||||
func resolve(_ container: DependencyContainer) throws
|
||||
}
|
||||
|
||||
#if swift(>=5.1)
|
||||
/**
|
||||
Use this wrapper to identify _strong_ properties of the instance that should be
|
||||
auto-injected by `DependencyContainer`. Type T can be any type.
|
||||
|
||||
- warning: Do not define this property as optional or container will not be able to inject it.
|
||||
Instead define it with initial value of `Injected<T>()`.
|
||||
|
||||
|
||||
**Example**:
|
||||
|
||||
```swift
|
||||
class ClientImp: Client {
|
||||
@Injected var service: Service?
|
||||
}
|
||||
```
|
||||
|
||||
- seealso: `InjectedWeak`
|
||||
|
||||
*/
|
||||
@propertyWrapper
|
||||
public struct Injected<T>: _InjectedPropertyBox, AutoInjectedPropertyBox {
|
||||
let valueBox: NullableBox<T> = NullableBox(nil)
|
||||
|
||||
///Wrapped value.
|
||||
public var wrappedValue: T? {
|
||||
get {
|
||||
return valueBox.unboxed
|
||||
}
|
||||
set {
|
||||
guard (required && newValue != nil) || !required else {
|
||||
fatalError("Can not set required property to nil.")
|
||||
}
|
||||
valueBox.unboxed = newValue
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let required: Bool
|
||||
let didInject: (T) -> ()
|
||||
let tag: DependencyContainer.Tag?
|
||||
let overrideTag: Bool
|
||||
|
||||
public init(wrappedValue initialValue: T?) {
|
||||
self.init()
|
||||
}
|
||||
}
|
||||
#else
|
||||
/**
|
||||
Use this wrapper to identify _strong_ properties of the instance that should be
|
||||
auto-injected by `DependencyContainer`. Type T can be any type.
|
||||
|
||||
- warning: Do not define this property as optional or container will not be able to inject it.
|
||||
Instead define it with initial value of `Injected<T>()`.
|
||||
|
||||
**Example**:
|
||||
|
||||
```swift
|
||||
class ClientImp: Client {
|
||||
var service = Injected<Service>()
|
||||
}
|
||||
```
|
||||
|
||||
- seealso: `InjectedWeak`
|
||||
|
||||
*/
|
||||
public final class Injected<T>: _InjectedPropertyBox<T>, AutoInjectedPropertyBox {
|
||||
|
||||
*/
|
||||
public struct Injected<T>: _InjectedPropertyBox, AutoInjectedPropertyBox {
|
||||
let valueBox: NullableBox<T> = NullableBox(nil)
|
||||
|
||||
///Wrapped value.
|
||||
public var value: T? {
|
||||
return valueBox.unboxed
|
||||
}
|
||||
|
||||
let required: Bool
|
||||
let didInject: (T) -> ()
|
||||
let tag: DependencyContainer.Tag?
|
||||
let overrideTag: Bool
|
||||
|
||||
/// Returns a new wrapper with provided value.
|
||||
func setValue(_ value: T?) -> Injected {
|
||||
guard (required && value != nil) || !required else {
|
||||
fatalError("Can not set required property to nil.")
|
||||
}
|
||||
|
||||
return Injected(value: value, required: required, tag: tag, overrideTag: overrideTag, didInject: didInject)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public extension Injected {
|
||||
///The type of wrapped property.
|
||||
public static var wrappedType: Any.Type {
|
||||
static var wrappedType: Any.Type {
|
||||
return T.self
|
||||
}
|
||||
|
||||
///Wrapped value.
|
||||
public internal(set) var value: T? {
|
||||
didSet {
|
||||
if let value = value { didInject(value) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
init(value: T?, required: Bool = true, tag: DependencyTagConvertible?, overrideTag: Bool, didInject: @escaping (T) -> ()) {
|
||||
self.value = value
|
||||
super.init(required: required, tag: tag, overrideTag: overrideTag, didInject: didInject)
|
||||
self.init(required: required, tag: tag, overrideTag: overrideTag, didInject: didInject)
|
||||
self.valueBox.unboxed = value
|
||||
}
|
||||
|
||||
init(required: Bool = true, tag: DependencyTagConvertible?, overrideTag: Bool, didInject: @escaping (T) -> () = { _ in }) {
|
||||
self.required = required
|
||||
self.tag = tag?.dependencyTag
|
||||
self.overrideTag = overrideTag
|
||||
self.didInject = didInject
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,30 +208,24 @@ public final class Injected<T>: _InjectedPropertyBox<T>, AutoInjectedPropertyBox
|
||||
- didInject: Block that will be called when concrete instance is injected in this property.
|
||||
Similar to `didSet` property observer. Default value does nothing.
|
||||
*/
|
||||
public convenience init(required: Bool = true, didInject: @escaping (T) -> () = { _ in }) {
|
||||
init(required: Bool = true, didInject: @escaping (T) -> () = { _ in }) {
|
||||
self.init(value: nil, required: required, tag: nil, overrideTag: false, didInject: didInject)
|
||||
}
|
||||
|
||||
public convenience init(required: Bool = true, tag: DependencyTagConvertible?, didInject: @escaping (T) -> () = { _ in }) {
|
||||
init(required: Bool = true, tag: DependencyTagConvertible?, didInject: @escaping (T) -> () = { _ in }) {
|
||||
self.init(value: nil, required: required, tag: tag, overrideTag: true, didInject: didInject)
|
||||
}
|
||||
|
||||
public func resolve(_ container: DependencyContainer) throws {
|
||||
let resolved: T? = try super.resolve(with: container)
|
||||
value = resolved
|
||||
}
|
||||
|
||||
/// Returns a new wrapper with provided value.
|
||||
public func setValue(_ value: T?) -> Injected {
|
||||
guard (required && value != nil) || !required else {
|
||||
fatalError("Can not set required property to nil.")
|
||||
func resolve(_ container: DependencyContainer) throws {
|
||||
let resolved: T? = try self.resolve(with: container, tag: tag, overrideTag: overrideTag, required: required)
|
||||
valueBox.unboxed = resolved
|
||||
if let resolved = resolved {
|
||||
didInject(resolved)
|
||||
}
|
||||
|
||||
return Injected(value: value, required: required, tag: tag, overrideTag: overrideTag, didInject: didInject)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if swift(>=5.1)
|
||||
/**
|
||||
Use this wrapper to identify _weak_ properties of the instance that should be
|
||||
auto-injected by `DependencyContainer`. Type T should be a **class** type.
|
||||
@@ -185,42 +247,124 @@ public final class Injected<T>: _InjectedPropertyBox<T>, AutoInjectedPropertyBox
|
||||
|
||||
```swift
|
||||
class ServiceImp: Service {
|
||||
var client = InjectedWeak<Client>()
|
||||
@InjectedWeak var client: Client?
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
- seealso: `Injected`
|
||||
|
||||
*/
|
||||
public final class InjectedWeak<T>: _InjectedPropertyBox<T>, AutoInjectedPropertyBox {
|
||||
@propertyWrapper
|
||||
public struct InjectedWeak<T>: _InjectedPropertyBox, AutoInjectedPropertyBox {
|
||||
|
||||
//Only classes (means AnyObject) can be used as `weak` properties
|
||||
//but we can not make <T: AnyObject> because that will prevent using protocol as generic type
|
||||
//so we just rely on user reading documentation and passing AnyObject in runtime
|
||||
//also we will throw fatal error if type can not be casted to AnyObject during resolution.
|
||||
|
||||
///The type of wrapped property.
|
||||
public static var wrappedType: Any.Type {
|
||||
return T.self
|
||||
}
|
||||
|
||||
var valueBox: WeakBox<T>? = nil {
|
||||
didSet {
|
||||
if let value = value { didInject(value) }
|
||||
|
||||
let valueBox: WeakBox<T> = WeakBox(nil)
|
||||
|
||||
///Wrapped value.
|
||||
public var wrappedValue: T? {
|
||||
get {
|
||||
return valueBox.value
|
||||
}
|
||||
set {
|
||||
guard (required && newValue != nil) || !required else {
|
||||
fatalError("Can not set required property to nil.")
|
||||
}
|
||||
|
||||
valueBox.unboxed = newValue as AnyObject
|
||||
}
|
||||
}
|
||||
|
||||
let required: Bool
|
||||
let didInject: (T) -> ()
|
||||
let tag: DependencyContainer.Tag?
|
||||
let overrideTag: Bool
|
||||
|
||||
public init(wrappedValue initialValue: T?) {
|
||||
self.init()
|
||||
}
|
||||
}
|
||||
#else
|
||||
/**
|
||||
Use this wrapper to identify _weak_ properties of the instance that should be
|
||||
auto-injected by `DependencyContainer`. Type T should be a **class** type.
|
||||
Otherwise it will cause runtime exception when container will try to resolve the property.
|
||||
Use this wrapper to define one of two circular dependencies to avoid retain cycle.
|
||||
|
||||
- note: The only difference between `InjectedWeak` and `Injected` is that `InjectedWeak` uses
|
||||
_weak_ reference to store underlying value, when `Injected` uses _strong_ reference.
|
||||
For that reason if you resolve instance that has a _weak_ auto-injected property this property
|
||||
will be released when `resolve` will complete.
|
||||
|
||||
Use `InjectedWeak<T>` to define one of two circular dependecies if another dependency is defined as `Injected<U>`.
|
||||
This will prevent a retain cycle between resolved instances.
|
||||
|
||||
- warning: Do not define this property as optional or container will not be able to inject it.
|
||||
Instead define it with initial value of `InjectedWeak<T>()`.
|
||||
|
||||
**Example**:
|
||||
|
||||
```swift
|
||||
class ServiceImp: Service {
|
||||
var client = InjectedWeak<Client>()
|
||||
}
|
||||
```
|
||||
|
||||
- seealso: `Injected`
|
||||
|
||||
*/
|
||||
public struct InjectedWeak<T>: _InjectedPropertyBox, AutoInjectedPropertyBox {
|
||||
|
||||
//Only classes (means AnyObject) can be used as `weak` properties
|
||||
//but we can not make <T: AnyObject> because that will prevent using protocol as generic type
|
||||
//so we just rely on user reading documentation and passing AnyObject in runtime
|
||||
//also we will throw fatal error if type can not be casted to AnyObject during resolution.
|
||||
|
||||
let valueBox: WeakBox<T> = WeakBox(nil)
|
||||
|
||||
///Wrapped value.
|
||||
public var value: T? {
|
||||
return valueBox?.value
|
||||
return valueBox.value
|
||||
}
|
||||
|
||||
init(value: T?, required: Bool = true, tag: DependencyTagConvertible?, overrideTag: Bool, didInject: @escaping (T) -> ()) {
|
||||
self.valueBox = value.map(WeakBox.init)
|
||||
super.init(required: required, tag: tag, overrideTag: overrideTag, didInject: didInject)
|
||||
let required: Bool
|
||||
let didInject: (T) -> ()
|
||||
let tag: DependencyContainer.Tag?
|
||||
let overrideTag: Bool
|
||||
|
||||
|
||||
/// Returns a new wrapper with provided value.
|
||||
func setValue(_ value: T?) -> InjectedWeak {
|
||||
guard (required && value != nil) || !required else {
|
||||
fatalError("Can not set required property to nil.")
|
||||
}
|
||||
|
||||
return InjectedWeak(value: value, required: required, tag: tag, overrideTag: overrideTag, didInject: didInject)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public extension InjectedWeak {
|
||||
///The type of wrapped property.
|
||||
static var wrappedType: Any.Type {
|
||||
return T.self
|
||||
}
|
||||
|
||||
init(value: T?, required: Bool = true, tag: DependencyTagConvertible?, overrideTag: Bool, didInject: @escaping (T) -> ()) {
|
||||
self.init(required: required, tag: tag, overrideTag: overrideTag, didInject: didInject)
|
||||
self.valueBox.unboxed = value as AnyObject
|
||||
}
|
||||
|
||||
init(required: Bool = true, tag: DependencyTagConvertible?, overrideTag: Bool, didInject: @escaping (T) -> () = { _ in }) {
|
||||
self.required = required
|
||||
self.tag = tag?.dependencyTag
|
||||
self.overrideTag = overrideTag
|
||||
self.didInject = didInject
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a new wrapper for weak auto-injected property.
|
||||
|
||||
@@ -232,46 +376,28 @@ public final class InjectedWeak<T>: _InjectedPropertyBox<T>, AutoInjectedPropert
|
||||
- didInject: Block that will be called when concrete instance is injected in this property.
|
||||
Similar to `didSet` property observer. Default value does nothing.
|
||||
*/
|
||||
public convenience init(required: Bool = true, didInject: @escaping (T) -> () = { _ in }) {
|
||||
init(required: Bool = true, didInject: @escaping (T) -> () = { _ in }) {
|
||||
self.init(value: nil, required: required, tag: nil, overrideTag: false, didInject: didInject)
|
||||
}
|
||||
|
||||
public convenience init(required: Bool = true, tag: DependencyTagConvertible?, didInject: @escaping (T) -> () = { _ in }) {
|
||||
init(required: Bool = true, tag: DependencyTagConvertible?, didInject: @escaping (T) -> () = { _ in }) {
|
||||
self.init(value: nil, required: required, tag: tag, overrideTag: true, didInject: didInject)
|
||||
}
|
||||
|
||||
public func resolve(_ container: DependencyContainer) throws {
|
||||
let resolved: T? = try super.resolve(with: container)
|
||||
valueBox = resolved.map(WeakBox.init)
|
||||
}
|
||||
|
||||
/// Returns a new wrapper with provided value.
|
||||
public func setValue(_ value: T?) -> InjectedWeak {
|
||||
guard (required && value != nil) || !required else {
|
||||
fatalError("Can not set required property to nil.")
|
||||
func resolve(_ container: DependencyContainer) throws {
|
||||
let resolved: T? = try self.resolve(with: container, tag: tag, overrideTag: overrideTag, required: required)
|
||||
valueBox.unboxed = resolved as AnyObject
|
||||
if let resolved = resolved {
|
||||
didInject(resolved)
|
||||
}
|
||||
|
||||
return InjectedWeak(value: value, required: required, tag: tag, overrideTag: overrideTag, didInject: didInject)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class _InjectedPropertyBox<T> {
|
||||
protocol _InjectedPropertyBox {}
|
||||
|
||||
let required: Bool
|
||||
let didInject: (T) -> ()
|
||||
let tag: DependencyContainer.Tag?
|
||||
let overrideTag: Bool
|
||||
|
||||
init(required: Bool = true, tag: DependencyTagConvertible?, overrideTag: Bool, didInject: @escaping (T) -> () = { _ in }) {
|
||||
self.required = required
|
||||
self.tag = tag?.dependencyTag
|
||||
self.overrideTag = overrideTag
|
||||
self.didInject = didInject
|
||||
}
|
||||
|
||||
func resolve(with container: DependencyContainer) throws -> T? {
|
||||
let tag = overrideTag ? self.tag : container.context.tag
|
||||
extension _InjectedPropertyBox {
|
||||
func resolve<T>(with container: DependencyContainer, tag: DependencyContainer.Tag?, overrideTag: Bool, required: Bool) throws -> T? {
|
||||
let tag = overrideTag ? tag : container.context.tag
|
||||
do {
|
||||
container.context.key = container.context.key.tagged(with: tag)
|
||||
let key = DefinitionKey(type: T.self, typeOfArguments: Void.self, tag: tag?.dependencyTag)
|
||||
@@ -289,12 +415,10 @@ public class _InjectedPropertyBox<T> {
|
||||
}
|
||||
}
|
||||
|
||||
private func resolve<U>(with container: DependencyContainer, key: DefinitionKey, builder: ((U) throws -> Any) throws -> Any) throws -> Any {
|
||||
func resolve<U>(with container: DependencyContainer, key: DefinitionKey, builder: ((U) throws -> Any) throws -> Any) throws -> Any {
|
||||
return try container._resolve(key: key, builder: { definition throws -> Any in
|
||||
try builder(definition.weakFactory)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,17 +1,5 @@
|
||||
#if _runtime(_ObjC)
|
||||
extension String {
|
||||
func has(prefix aPrefix: String) -> Bool {
|
||||
return hasPrefix(aPrefix)
|
||||
}
|
||||
extension String {
|
||||
func has(prefix aPrefix: String) -> Bool {
|
||||
return hasPrefix(aPrefix)
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
extension String {
|
||||
func has(prefix aPrefix: String) -> Bool {
|
||||
return aPrefix ==
|
||||
String(self.characters.prefix(aPrefix.characters.count))
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -35,10 +35,10 @@ public enum ComponentScope {
|
||||
```
|
||||
container.register { ServiceImp() as Service }
|
||||
container.register {
|
||||
ServiceConsumerImp(
|
||||
service1: try container.resolve() as Service
|
||||
service2: try container.resolve() as Service
|
||||
) as ServiceConsumer
|
||||
ServiceConsumerImp(
|
||||
service1: try container.resolve() as Service
|
||||
service2: try container.resolve() as Service
|
||||
) as ServiceConsumer
|
||||
}
|
||||
let consumer = container.resolve() as ServiceConsumer
|
||||
consumer.service1 !== consumer.service2 //true
|
||||
@@ -59,10 +59,10 @@ public enum ComponentScope {
|
||||
```
|
||||
container.register { ServiceImp() as Service }
|
||||
container.register {
|
||||
ServiceConsumerImp(
|
||||
service1: try container.resolve() as Service
|
||||
service2: try container.resolve() as Service
|
||||
) as ServiceConsumer
|
||||
ServiceConsumerImp(
|
||||
service1: try container.resolve() as Service
|
||||
service2: try container.resolve() as Service
|
||||
) as ServiceConsumer
|
||||
}
|
||||
let consumer1 = container.resolve() as ServiceConsumer
|
||||
let consumer2 = container.resolve() as ServiceConsumer
|
||||
@@ -89,10 +89,10 @@ public enum ComponentScope {
|
||||
```
|
||||
container.register(.singleton) { ServiceImp() as Service }
|
||||
container.register {
|
||||
ServiceConsumerImp(
|
||||
service1: try container.resolve() as Service
|
||||
service2: try container.resolve() as Service
|
||||
) as ServiceConsumer
|
||||
ServiceConsumerImp(
|
||||
service1: try container.resolve() as Service
|
||||
service2: try container.resolve() as Service
|
||||
) as ServiceConsumer
|
||||
}
|
||||
let consumer1 = container.resolve() as ServiceConsumer
|
||||
let consumer2 = container.resolve() as ServiceConsumer
|
||||
|
||||
@@ -34,12 +34,14 @@ public struct DefinitionKey: Hashable, CustomStringConvertible {
|
||||
self.tag = tag
|
||||
}
|
||||
|
||||
public var hashValue: Int {
|
||||
return "\(type)-\(typeOfArguments)-\(tag.desc)".hashValue
|
||||
public func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(ObjectIdentifier(type))
|
||||
hasher.combine(ObjectIdentifier(typeOfArguments))
|
||||
hasher.combine(tag.desc)
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
return "type: \(type), arguments: \(typeOfArguments), tag: \(tag.desc)"
|
||||
return "type: \(String(reflecting: type)), arguments: \(typeOfArguments), tag: \(tag.desc)"
|
||||
}
|
||||
|
||||
func tagged(with tag: DependencyContainer.Tag?) -> DefinitionKey {
|
||||
@@ -53,7 +55,7 @@ public struct DefinitionKey: Hashable, CustomStringConvertible {
|
||||
return
|
||||
lhs.type == rhs.type &&
|
||||
lhs.typeOfArguments == rhs.typeOfArguments &&
|
||||
lhs.tag == rhs.tag
|
||||
lhs.tag.desc == rhs.tag.desc
|
||||
}
|
||||
|
||||
}
|
||||
@@ -80,6 +82,7 @@ public final class Definition<T, U>: DefinitionType {
|
||||
let scope: ComponentScope
|
||||
var weakFactory: ((Any) throws -> Any)!
|
||||
var resolveProperties: ((DependencyContainer, Any) throws -> ())?
|
||||
var autoInjectProperties: Bool?
|
||||
|
||||
init(scope: ComponentScope, factory: @escaping F) {
|
||||
self.factory = factory
|
||||
@@ -125,6 +128,34 @@ public final class Definition<T, U>: DefinitionType {
|
||||
return self
|
||||
}
|
||||
|
||||
@discardableResult public func resolvingProperty<Root, V>(_ keyPath: ReferenceWritableKeyPath<Root, V>, as type: Any.Type = V.self, tag: DependencyTagConvertible? = nil) -> Definition {
|
||||
return resolvingProperties { (container, instance) in
|
||||
precondition(instance is Root, "Type of resolved instance \(Swift.type(of: instance)) does not match expected type \(Root.self)")
|
||||
let resolved = try container.resolve(type, tag: tag)
|
||||
precondition(resolved is V, "Type of resolved property \(Swift.type(of: resolved)) does not match expected type \(type)")
|
||||
(instance as! Root)[keyPath: keyPath] = resolved as! V
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult public func resolvingProperty<Root, V>(_ keyPath: ReferenceWritableKeyPath<Root, V>, factory: @escaping (DependencyContainer) throws -> V = { try $0.resolve() }) -> Definition {
|
||||
return resolvingProperties { (container, instance) in
|
||||
precondition(instance is Root, "Type of resolved instance \(Swift.type(of: instance)) does not match expected type \(Root.self)")
|
||||
(instance as! Root)[keyPath: keyPath] = try factory(container)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Whether container should perform properties auto-injection when resolving using this definition.
|
||||
If called will override container configuration. Can be called together with `resolvingProperties`
|
||||
to resolve properties that are not automatically injected.
|
||||
|
||||
- parameter shouldAutoInject: Whether container should perform properties auto-injection when resolving using this definition. Default is `true`.
|
||||
*/
|
||||
@discardableResult public func autoInjectingProperties(_ shouldAutoInject: Bool = true) -> Definition {
|
||||
autoInjectProperties = shouldAutoInject
|
||||
return self
|
||||
}
|
||||
|
||||
/// Calls `resolveDependencies` block if it was set.
|
||||
func resolveProperties(of instance: Any, container: DependencyContainer) throws {
|
||||
guard let resolvedInstance = instance as? T else { return }
|
||||
@@ -144,7 +175,7 @@ public final class Definition<T, U>: DefinitionType {
|
||||
//MARK: - TypeForwardingDefinition
|
||||
|
||||
/// Types that can be resolved using this definition.
|
||||
private(set) var implementingTypes: [Any.Type] = [(T?).self, (T!).self]
|
||||
private(set) var implementingTypes: [Any.Type] = [(T?).self]
|
||||
|
||||
/// Return `true` if type can be resolved using this definition
|
||||
func doesImplements(type aType: Any.Type) -> Bool {
|
||||
@@ -204,6 +235,7 @@ protocol _Definition: AutoWiringDefinition, TypeForwardingDefinition {
|
||||
var weakFactory: ((Any) throws -> Any)! { get }
|
||||
func resolveProperties(of instance: Any, container: DependencyContainer) throws
|
||||
var container: DependencyContainer? { get set }
|
||||
var autoInjectProperties: Bool? { get }
|
||||
}
|
||||
|
||||
//MARK: - Type Forwarding
|
||||
|
||||
+15
-4
@@ -38,7 +38,9 @@ public final class DependencyContainer {
|
||||
case String(StringLiteralType)
|
||||
case Int(IntegerLiteralType)
|
||||
}
|
||||
|
||||
|
||||
var autoInjectProperties: Bool
|
||||
var threadSafe: Bool
|
||||
internal(set) public var context: Context!
|
||||
var definitions = [DefinitionKey: _Definition]()
|
||||
var resolvedInstances = ResolvedInstances()
|
||||
@@ -59,8 +61,11 @@ public final class DependencyContainer {
|
||||
|
||||
/**
|
||||
Designated initializer for a DependencyContainer
|
||||
|
||||
- parameter configBlock: A configuration block in which you typically put all you `register` calls.
|
||||
|
||||
- Parameters:
|
||||
- autoInjectProperties: Whether container should perform properties auto-injection. Default is `true`.
|
||||
- threadSafe: Whether container should be thread-safe. Default is `true`. You may want to disable it for better performance.
|
||||
- configBlock: A configuration block in which you typically put all you `register` calls.
|
||||
|
||||
- note: The `configBlock` is simply called at the end of the `init` to let you configure everything.
|
||||
It is only present for convenience to have a cleaner syntax when declaring and initializing
|
||||
@@ -79,7 +84,9 @@ public final class DependencyContainer {
|
||||
|
||||
- returns: A new DependencyContainer.
|
||||
*/
|
||||
public init(configBlock: (DependencyContainer)->() = { _ in }) {
|
||||
public init(autoInjectProperties: Bool = true, threadSafe: Bool = true, configBlock: (DependencyContainer)->() = { _ in }) {
|
||||
self.autoInjectProperties = autoInjectProperties
|
||||
self.threadSafe = threadSafe
|
||||
configBlock(self)
|
||||
}
|
||||
|
||||
@@ -100,6 +107,10 @@ public final class DependencyContainer {
|
||||
}
|
||||
|
||||
func threadSafe<T>(_ closure: () throws -> T) rethrows -> T {
|
||||
guard threadSafe else {
|
||||
return try closure()
|
||||
}
|
||||
|
||||
lock.lock()
|
||||
defer { lock.unlock() }
|
||||
return try closure()
|
||||
|
||||
@@ -77,18 +77,16 @@ public enum DipError: Error, CustomStringConvertible {
|
||||
public var description: String {
|
||||
switch self {
|
||||
case let .definitionNotFound(key):
|
||||
return "No definition registered for \(key).\nCheck the tag, type you try to resolve, number, order and types of runtime arguments passed to `resolve()` and match them with registered factories for type \(key.type)."
|
||||
return "No definition registered for \(key).\nCheck the tag, type you try to resolve, number, order and types of runtime arguments passed to `resolve()` and match them with registered factories for type \(String(reflecting: key.type))."
|
||||
case let .autoInjectionFailed(label, type, error):
|
||||
return "Failed to auto-inject property \"\(label.desc)\" of type \(type). \(error)"
|
||||
return "Failed to auto-inject property \"\(label.desc)\" of type \(String(reflecting: type)). \(error)"
|
||||
case let .autoWiringFailed(type, error):
|
||||
return "Failed to auto-wire type \"\(type)\". \(error)"
|
||||
return "Failed to auto-wire type \"\(String(reflecting: type))\". \(error)"
|
||||
case let .ambiguousDefinitions(type, definitions):
|
||||
return "Ambiguous definitions for \(type):\n" +
|
||||
return "Ambiguous definitions for \(String(reflecting: type)):\n" +
|
||||
definitions.map({ "\($0)" }).joined(separator: ";\n")
|
||||
case let .invalidType(resolved, key):
|
||||
return "Resolved instance \(resolved ?? "nil") does not implement expected type \(key.type)."
|
||||
return "Resolved instance \(resolved ?? "nil") does not implement expected type \(String(reflecting: key.type))."
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
+16
-11
@@ -183,7 +183,7 @@ extension DependencyContainer {
|
||||
return previouslyResolved
|
||||
}
|
||||
|
||||
log(level: .Verbose, context)
|
||||
if let context = context { log(level: .Verbose, context) }
|
||||
var resolvedInstance = try builder(definition)
|
||||
|
||||
/*
|
||||
@@ -199,7 +199,7 @@ extension DependencyContainer {
|
||||
That happens because when Optional is casted to Any Swift can not implicitly unwrap it with as operator.
|
||||
As a workaround we detect boxing here and unwrap it so that we return not a box, but wrapped instance.
|
||||
*/
|
||||
if let box = resolvedInstance as? BoxType, let unboxed = box.unboxed as? T {
|
||||
if let box = resolvedInstance as? BoxType, let unboxedAny = box.unboxed, let unboxed = unboxedAny as? T {
|
||||
resolvedInstance = unboxed
|
||||
}
|
||||
|
||||
@@ -217,8 +217,11 @@ extension DependencyContainer {
|
||||
resolvedInstances.resolvableInstances.append(resolvable)
|
||||
resolvable.resolveDependencies(self)
|
||||
}
|
||||
|
||||
try autoInjectProperties(in: resolvedInstance)
|
||||
|
||||
let shouldAutoInject = definition.autoInjectProperties ?? self.autoInjectProperties
|
||||
if shouldAutoInject {
|
||||
try autoInjectProperties(in: resolvedInstance)
|
||||
}
|
||||
try definition.resolveProperties(of: resolvedInstance, container: self)
|
||||
|
||||
log(level: .Verbose, "Resolved type \(key.type) with \(resolvedInstance)")
|
||||
@@ -227,7 +230,7 @@ extension DependencyContainer {
|
||||
|
||||
private func previouslyResolved<T>(for definition: _Definition, key: DefinitionKey) -> T? {
|
||||
//first check if exact key was already resolved
|
||||
if let previouslyResolved = resolvedInstances[key: key, inScope: definition.scope, context: context] as? T {
|
||||
if let previouslyResolved: T = resolvedInstances[key: key, inScope: definition.scope, context: context] {
|
||||
return previouslyResolved
|
||||
}
|
||||
//then check if any related type was already resolved
|
||||
@@ -235,7 +238,7 @@ extension DependencyContainer {
|
||||
DefinitionKey(type: $0, typeOfArguments: key.typeOfArguments, tag: key.tag)
|
||||
})
|
||||
for key in keys {
|
||||
if let previouslyResolved = resolvedInstances[key: key, inScope: definition.scope, context: context] as? T {
|
||||
if let previouslyResolved: T = resolvedInstances[key: key, inScope: definition.scope, context: context] {
|
||||
return previouslyResolved
|
||||
}
|
||||
}
|
||||
@@ -280,20 +283,22 @@ class ResolvedInstances {
|
||||
}
|
||||
var weakSingletons = [DefinitionKey: Any]()
|
||||
|
||||
subscript(key key: DefinitionKey, inScope scope: ComponentScope, context context: DependencyContainer.Context) -> Any? {
|
||||
subscript<T>(key key: DefinitionKey, inScope scope: ComponentScope, context context: DependencyContainer.Context) -> T? {
|
||||
get {
|
||||
let instance: Any?
|
||||
switch scope {
|
||||
case .singleton, .eagerSingleton:
|
||||
return context.inCollaboration ? sharedSingletons[key] : singletons[key]
|
||||
instance = context.inCollaboration ? sharedSingletons[key] : singletons[key]
|
||||
case .weakSingleton:
|
||||
let singletons = context.inCollaboration ? sharedWeakSingletons : weakSingletons
|
||||
if let boxed = singletons[key] as? WeakBoxType { return boxed.unboxed }
|
||||
else { return singletons[key] }
|
||||
if let boxed = singletons[key] as? WeakBoxType { instance = boxed.unboxed }
|
||||
else { instance = singletons[key] }
|
||||
case .shared:
|
||||
return resolvedInstances[key]
|
||||
instance = resolvedInstances[key]
|
||||
case .unique:
|
||||
return nil
|
||||
}
|
||||
return instance.flatMap { $0 as? T }
|
||||
}
|
||||
set {
|
||||
switch scope {
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
//
|
||||
// DipUI
|
||||
//
|
||||
// Copyright (c) 2016 Ilya Puchka <ilyapuchka@gmail.com>
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#if (canImport(UIKit) || canImport(AppKit) || canImport(WatchKit))
|
||||
|
||||
extension DependencyContainer {
|
||||
///Containers that will be used to resolve dependencies of instances, created by stroyboards.
|
||||
static public var uiContainers: [DependencyContainer] = {
|
||||
#if os(watchOS)
|
||||
swizzleAwakeWithContext
|
||||
#endif
|
||||
return []
|
||||
}()
|
||||
|
||||
/**
|
||||
Resolves dependencies of passed in instance.
|
||||
Use this method to resolve dependencies of object created by storyboard.
|
||||
The type of the instance should be registered in the container.
|
||||
|
||||
You should call this method only from implementation of `didInstantiateFromStoryboard(_:tag:)`
|
||||
of `StoryboardInstantiatable` protocol if you override its default implementation.
|
||||
|
||||
This method will do the same as `resolve(tag:) as T`, but instead of creating
|
||||
a new intance with a registered factory it will use passed in instance as a resolved instance.
|
||||
|
||||
- parameters:
|
||||
- instance: The object which dependencies should be resolved
|
||||
- tag: An optional tag used to register the type (`T`) in the container
|
||||
|
||||
**Example**:
|
||||
|
||||
```swift
|
||||
class ViewController: UIViewController, ServiceDelegate, StoryboardInstantiatable {
|
||||
var service: Service?
|
||||
|
||||
func didInstantiateFromStoryboard(_ container: DependencyContainer, tag: DependencyContainer.Tag?) throws {
|
||||
try container.resolveDependencies(of: self as ServiceDelegate, tag: "vc")
|
||||
}
|
||||
}
|
||||
|
||||
class ServiceImp: Service {
|
||||
weak var delegate: ServiceDelegate?
|
||||
}
|
||||
|
||||
container.register(tag: "vc") { ViewController() }
|
||||
.resolvingProperties { container, controller in
|
||||
controller.service = try container.resolve() as Service
|
||||
controller.service.delegate = controller
|
||||
}
|
||||
|
||||
container.register { ServiceImp() as Service }
|
||||
```
|
||||
|
||||
- seealso: `register(_:type:tag:factory:)`, `didInstantiateFromStoryboard(_:tag:)`
|
||||
|
||||
*/
|
||||
public func resolveDependencies<T>(of instance: T, tag: Tag? = nil) throws {
|
||||
_ = try resolve(tag: tag) { (_: () throws -> T) in instance }
|
||||
}
|
||||
|
||||
/**
|
||||
Register storyboard type `T` which has to conform to `StoryboardInstantiatable` and associate it with an optional tag.
|
||||
|
||||
- parameters:
|
||||
- type: Storyboard type to register definition for.
|
||||
- tag: The arbitrary tag to associate this factory with. Pass `nil` to associate with any tag. Default value is `nil`.
|
||||
|
||||
- returns: A registered definition.
|
||||
|
||||
- note: This method will register concrete types. If you need to register
|
||||
as abstract types you should use standard `register` method from Dip.
|
||||
You should cast the factory return type to the protocol you want to
|
||||
register it for (unless you want to register concrete type) or
|
||||
provide `type` parameter.
|
||||
|
||||
- seealso: `Definition`, `ComponentScope`, `DependencyTagConvertible`
|
||||
|
||||
**Example**:
|
||||
```swift
|
||||
// Register MyViewController
|
||||
container.register(storyboardType: MyViewController.self)
|
||||
// or
|
||||
container.register(tag: "myVC") { MyViewController() as MyViewControllerType }
|
||||
```
|
||||
*/
|
||||
public func register<T: NSObject>(storyboardType type: T.Type, tag: DependencyTagConvertible? = nil) -> Dip.Definition<T, ()> where T: StoryboardInstantiatable {
|
||||
return register(.unique, type: type, tag: tag, factory: { T() })
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if os(watchOS)
|
||||
public protocol StoryboardInstantiatableType {}
|
||||
#else
|
||||
public typealias StoryboardInstantiatableType = NSObjectProtocol
|
||||
#endif
|
||||
|
||||
public protocol StoryboardInstantiatable: StoryboardInstantiatableType {
|
||||
|
||||
/**
|
||||
This method will be called if you set a `dipTag` attirbute on the object in a storyboard
|
||||
that conforms to `StoryboardInstantiatable` protocol.
|
||||
|
||||
- parameters:
|
||||
- tag: The tag value, that was set on the object in a storyboard
|
||||
- container: The `DependencyContainer` associated with storyboards
|
||||
|
||||
The type that implements `StoryboardInstantiatable` protocol should be registered in `UIStoryboard.container`.
|
||||
Default implementation of that method calls `resolveDependenciesOf(_:tag:)`
|
||||
and pass it `self` instance and the tag.
|
||||
|
||||
Usually you will not need to override the default implementation of this method
|
||||
if you registered the type of the instance as a concrete type in the container.
|
||||
Then you only need to add conformance to `StoryboardInstantiatable`.
|
||||
|
||||
You may want to override it if you want to add custom logic before/after resolving dependencies
|
||||
or you want to resolve the instance as implementation of some protocol which it conforms to.
|
||||
|
||||
- warning: This method will be called after `init?(coder:)` but before `awakeFromNib` method of `NSObject`.
|
||||
On watchOS this method will be called before `awakeWithContext(_:)`.
|
||||
|
||||
**Example**:
|
||||
|
||||
```swift
|
||||
extension MyViewController: SomeProtocol { ... }
|
||||
|
||||
extension MyViewController: StoryboardInstantiatable {
|
||||
func didInstantiateFromStoryboard(_ container: DependencyContainer, tag: DependencyContainer.Tag) throws {
|
||||
//resolve dependencies of the instance as SomeProtocol type
|
||||
try container.resolveDependencies(of: self as SomeProtocol, tag: tag)
|
||||
//do some additional setup here
|
||||
}
|
||||
}
|
||||
```
|
||||
*/
|
||||
func didInstantiateFromStoryboard(_ container: DependencyContainer, tag: DependencyContainer.Tag?) throws
|
||||
|
||||
}
|
||||
|
||||
extension StoryboardInstantiatable {
|
||||
public func didInstantiateFromStoryboard(_ container: DependencyContainer, tag: DependencyContainer.Tag?) throws {
|
||||
try container.resolveDependencies(of: self, tag: tag)
|
||||
}
|
||||
}
|
||||
|
||||
#if os(iOS) || os(tvOS) || os(OSX)
|
||||
|
||||
#if os(iOS) || os(tvOS)
|
||||
import UIKit
|
||||
#elseif os(OSX)
|
||||
import AppKit
|
||||
#endif
|
||||
|
||||
let DipTagAssociatedObjectKey = UnsafeMutablePointer<Int8>.allocate(capacity: 1)
|
||||
|
||||
extension NSObject {
|
||||
|
||||
///A string tag that will be used to resolve dependencies of this instance
|
||||
///if it implements `StoryboardInstantiatable` protocol.
|
||||
@objc private(set) public var dipTag: String? {
|
||||
get {
|
||||
return objc_getAssociatedObject(self, DipTagAssociatedObjectKey) as? String
|
||||
}
|
||||
set {
|
||||
objc_setAssociatedObject(self, DipTagAssociatedObjectKey, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
|
||||
guard let instantiatable = self as? StoryboardInstantiatable else { return }
|
||||
|
||||
let tag = dipTag.map(DependencyContainer.Tag.String)
|
||||
|
||||
for (index, container) in DependencyContainer.uiContainers.enumerated() {
|
||||
do {
|
||||
log("Trying to resolve \(type(of: self)) with UI container at index \(index)")
|
||||
try instantiatable.didInstantiateFromStoryboard(container, tag: tag)
|
||||
log("Resolved \(type(of: self))")
|
||||
return
|
||||
} catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func log(_ message: Any) {
|
||||
if Dip.LogLevel.Errors.rawValue <= Dip.logLevel.rawValue {
|
||||
Dip.logger(logLevel, message)
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
import WatchKit
|
||||
|
||||
let swizzleAwakeWithContext: Void = {
|
||||
let originalSelector = #selector(WKInterfaceController.awake(withContext:))
|
||||
let swizzledSelector = #selector(WKInterfaceController.dip_awake(withContext:))
|
||||
|
||||
guard let originalMethod = class_getInstanceMethod(WKInterfaceController.self, originalSelector),
|
||||
let swizzledMethod = class_getInstanceMethod(WKInterfaceController.self, swizzledSelector) else { return }
|
||||
|
||||
let didAddMethod = class_addMethod(WKInterfaceController.self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
|
||||
|
||||
if didAddMethod {
|
||||
class_replaceMethod(WKInterfaceController.self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
|
||||
} else {
|
||||
method_exchangeImplementations(originalMethod, swizzledMethod)
|
||||
}
|
||||
}()
|
||||
|
||||
extension WKInterfaceController: StoryboardInstantiatableType {
|
||||
|
||||
@objc func dip_awake(withContext context: AnyObject?) {
|
||||
defer { self.dip_awake(withContext: context) }
|
||||
guard let instantiatable = self as? StoryboardInstantiatable else { return }
|
||||
|
||||
for container in DependencyContainer.uiContainers {
|
||||
guard let _ = try? instantiatable.didInstantiateFromStoryboard(container, tag: nil) else { continue }
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+9
-14
@@ -48,11 +48,6 @@ extension Optional: BoxType {
|
||||
}
|
||||
}
|
||||
|
||||
extension ImplicitlyUnwrappedOptional: BoxType {
|
||||
var unboxed: Any? {
|
||||
return self ?? nil
|
||||
}
|
||||
}
|
||||
|
||||
class Box<T> {
|
||||
var unboxed: T
|
||||
@@ -61,6 +56,13 @@ class Box<T> {
|
||||
}
|
||||
}
|
||||
|
||||
class NullableBox<T> {
|
||||
var unboxed: T?
|
||||
init(_ value: T?) {
|
||||
self.unboxed = value
|
||||
}
|
||||
}
|
||||
|
||||
protocol WeakBoxType {
|
||||
var unboxed: AnyObject? { get }
|
||||
}
|
||||
@@ -71,15 +73,8 @@ class WeakBox<T>: WeakBoxType {
|
||||
return unboxed as? T
|
||||
}
|
||||
|
||||
init(_ value: T) {
|
||||
#if _runtime(_ObjC)
|
||||
weak var value: AnyObject? = value as AnyObject
|
||||
#else
|
||||
weak var value: AnyObject? = value as? AnyObject
|
||||
#endif
|
||||
guard value != nil else {
|
||||
fatalError("Can not store weak reference to not a class instance (\(T.self))")
|
||||
}
|
||||
init(_ value: T?) {
|
||||
weak var value: AnyObject? = value as AnyObject
|
||||
self.unboxed = value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import XCTest
|
||||
@testable import Dip
|
||||
|
||||
private protocol Server: class {
|
||||
weak var client: Client! {get}
|
||||
var client: Client! {get}
|
||||
var anotherClient: Client! {get set}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,34 @@ private protocol Client: class {
|
||||
var anotherServer: Server! {get set}
|
||||
}
|
||||
|
||||
#if swift(>=5.1)
|
||||
private class ServerImp: Server {
|
||||
|
||||
@InjectedWeak(didInject: { _ in
|
||||
AutoInjectionTests.clientDidInjectCalled = true
|
||||
}) var client: Client!
|
||||
|
||||
@InjectedWeak(required: false) var _optionalProperty: AnyObject?
|
||||
|
||||
weak var anotherClient: Client!
|
||||
}
|
||||
|
||||
private class ClientImp: Client {
|
||||
|
||||
@Injected(didInject: { _ in
|
||||
AutoInjectionTests.serverDidInjectCalled = true
|
||||
}) var server: Server
|
||||
|
||||
@Injected(required: false) var _optionalProperty: AnyObject?
|
||||
|
||||
@Injected(tag: "tagged") var taggedServer: Server
|
||||
@Injected(tag: nil) var nilTaggedServer: Server
|
||||
|
||||
var anotherServer: Server!
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
private class ServerImp: Server {
|
||||
|
||||
var _client = InjectedWeak<Client>() { _ in
|
||||
@@ -47,7 +75,7 @@ private class ServerImp: Server {
|
||||
|
||||
weak var anotherClient: Client!
|
||||
|
||||
weak var _optionalProperty = InjectedWeak<AnyObject>(required: false)
|
||||
var _optionalProperty = InjectedWeak<AnyObject>(required: false)
|
||||
}
|
||||
|
||||
private class ClientImp: Client {
|
||||
@@ -67,7 +95,18 @@ private class ClientImp: Client {
|
||||
var taggedServer = Injected<Server>(tag: "tagged")
|
||||
var nilTaggedServer = Injected<Server>(tag: nil)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if swift(>=5.1)
|
||||
private class Obj1 {
|
||||
@InjectedWeak var obj2: Obj2?
|
||||
@Injected var obj3: Obj3?
|
||||
}
|
||||
|
||||
private class Obj2 {
|
||||
@Injected var obj1: Obj1?
|
||||
}
|
||||
#else
|
||||
private class Obj1 {
|
||||
let obj2 = InjectedWeak<Obj2>()
|
||||
let obj3 = Injected<Obj3>()
|
||||
@@ -76,6 +115,7 @@ private class Obj1 {
|
||||
private class Obj2 {
|
||||
let obj1 = Injected<Obj1>()
|
||||
}
|
||||
#endif
|
||||
|
||||
private class Obj3 {
|
||||
|
||||
@@ -92,26 +132,6 @@ class AutoInjectionTests: XCTestCase {
|
||||
static var clientDidInjectCalled: Bool = false
|
||||
|
||||
let container = DependencyContainer()
|
||||
|
||||
static var allTests = {
|
||||
return [
|
||||
("testThatItResolvesAutoInjectedDependencies", testThatItResolvesAutoInjectedDependencies),
|
||||
("testThatItResolvesInheritedDependencies", testThatItResolvesInheritedDependencies),
|
||||
("testThatItCanSetInjectedProperty", testThatItCanSetInjectedProperty),
|
||||
("testThatItThrowsErrorIfFailsToAutoInjectDependency", testThatItThrowsErrorIfFailsToAutoInjectDependency),
|
||||
("testThatItResolvesAutoInjectedSingletons", testThatItResolvesAutoInjectedSingletons),
|
||||
("testThatItCallsResolveDependencyBlockWhenAutoInjecting", testThatItCallsResolveDependencyBlockWhenAutoInjecting),
|
||||
("testThatItReusesResolvedAutoInjectedInstances", testThatItReusesResolvedAutoInjectedInstances),
|
||||
("testThatItReusesAutoInjectedInstancesOnNextResolveOrAutoInjection", testThatItReusesAutoInjectedInstancesOnNextResolveOrAutoInjection),
|
||||
("testThatThereIsNoRetainCycleBetweenAutoInjectedCircularDependencies", testThatThereIsNoRetainCycleBetweenAutoInjectedCircularDependencies),
|
||||
("testThatItCallsDidInjectOnAutoInjectedProperty", testThatItCallsDidInjectOnAutoInjectedProperty),
|
||||
("testThatNoErrorThrownWhenOptionalPropertiesAreNotAutoInjected", testThatNoErrorThrownWhenOptionalPropertiesAreNotAutoInjected),
|
||||
("testThatItResolvesTaggedAutoInjectedProperties", testThatItResolvesTaggedAutoInjectedProperties),
|
||||
("testThatItPassesTagToAutoInjectedProperty", testThatItPassesTagToAutoInjectedProperty),
|
||||
("testThatItDoesNotPassTagToAutoInjectedPropertyWithExplicitTag", testThatItDoesNotPassTagToAutoInjectedPropertyWithExplicitTag),
|
||||
("testThatItAutoInjectsPropertyWithCollaboratingContainer", testThatItAutoInjectsPropertyWithCollaboratingContainer)
|
||||
]
|
||||
}()
|
||||
|
||||
override func setUp() {
|
||||
container.reset()
|
||||
@@ -128,10 +148,18 @@ class AutoInjectionTests: XCTestCase {
|
||||
|
||||
func testThatItResolvesInheritedDependencies() {
|
||||
class ServerImp2: ServerImp {
|
||||
#if swift(>=5.1)
|
||||
@InjectedWeak(didInject: { _ in
|
||||
XCTAssertTrue(AutoInjectionTests.serverDidInjectCalled, "Inherited properties should be resolved first")
|
||||
}) var client2: Client?
|
||||
#else
|
||||
var _client2 = InjectedWeak<Client>() { _ in
|
||||
XCTAssertTrue(AutoInjectionTests.serverDidInjectCalled, "Inherited properties should be resolved first")
|
||||
}
|
||||
var client2: Client? { return _client2.value }
|
||||
var client2: Client? {
|
||||
return _client2.value
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
container.register { ServerImp2() as Server }
|
||||
@@ -153,17 +181,23 @@ class AutoInjectionTests: XCTestCase {
|
||||
|
||||
let newServer = ServerImp()
|
||||
let newClient = ClientImp()
|
||||
#if swift(>=5.1)
|
||||
client.server = newServer
|
||||
server.client = newClient
|
||||
#else
|
||||
client._server = client._server.setValue(newServer)
|
||||
server._client = server._client.setValue(newClient)
|
||||
#endif
|
||||
|
||||
XCTAssertTrue(client.server === newServer)
|
||||
XCTAssertTrue(server.client === newClient)
|
||||
}
|
||||
|
||||
|
||||
|
||||
func testThatItThrowsErrorIfFailsToAutoInjectDependency() {
|
||||
container.register { ClientImp() as Client }
|
||||
|
||||
AssertThrows(expression: try container.resolve() as Client)
|
||||
XCTAssertThrowsError(try self.container.resolve() as Client)
|
||||
}
|
||||
|
||||
func testThatItResolvesAutoInjectedSingletons() {
|
||||
@@ -245,11 +279,19 @@ class AutoInjectionTests: XCTestCase {
|
||||
let obj2 = try! container.resolve() as Obj2
|
||||
|
||||
//then
|
||||
XCTAssertTrue(obj2 === obj2.obj1.value!.obj2.value!,
|
||||
#if swift(>=5.1)
|
||||
XCTAssertTrue(obj2 === obj2.obj1!.obj2!,
|
||||
"Auto-injected instance should be reused on next auto-injection")
|
||||
|
||||
XCTAssertTrue(obj2.obj1.value! === obj2.obj1.value!.obj3.value!.obj1,
|
||||
XCTAssertTrue(obj2.obj1! === obj2.obj1!.obj3!.obj1,
|
||||
"Auto-injected instance should be reused on next resolve")
|
||||
#else
|
||||
XCTAssertTrue(obj2 === obj2.obj1.value!.obj2.value!,
|
||||
"Auto-injected instance should be reused on next auto-injection")
|
||||
|
||||
XCTAssertTrue(obj2.obj1.value! === obj2.obj1.value!.obj3.value!.obj1,
|
||||
"Auto-injected instance should be reused on next resolve")
|
||||
#endif
|
||||
}
|
||||
|
||||
func testThatThereIsNoRetainCycleBetweenAutoInjectedCircularDependencies() {
|
||||
@@ -294,7 +336,10 @@ class AutoInjectionTests: XCTestCase {
|
||||
container.register { ServerImp() as Server }
|
||||
container.register { ClientImp() as Client }
|
||||
|
||||
AssertNoThrow(expression: try container.resolve() as Client, "Container should not throw error if failed to resolve optional auto-injected properties.")
|
||||
XCTAssertNoThrow(
|
||||
try container.resolve() as Client,
|
||||
"Container should not throw error if failed to resolve optional auto-injected properties."
|
||||
)
|
||||
}
|
||||
|
||||
func testThatItResolvesTaggedAutoInjectedProperties() {
|
||||
@@ -307,7 +352,11 @@ class AutoInjectionTests: XCTestCase {
|
||||
let client = try! container.resolve() as Client
|
||||
|
||||
//then
|
||||
#if swift(>=5.1)
|
||||
let taggedServer = (client as! ClientImp).taggedServer!
|
||||
#else
|
||||
let taggedServer = (client as! ClientImp).taggedServer.value!
|
||||
#endif
|
||||
let server = client.server!
|
||||
|
||||
//server and tagged server should be resolved as different instances
|
||||
@@ -326,7 +375,11 @@ class AutoInjectionTests: XCTestCase {
|
||||
let client = try! container.resolve(tag: "tagged") as Client
|
||||
|
||||
//then
|
||||
#if swift(>=5.1)
|
||||
let taggedServer = (client as! ClientImp).taggedServer!
|
||||
#else
|
||||
let taggedServer = (client as! ClientImp).taggedServer.value!
|
||||
#endif
|
||||
let server = client.server!
|
||||
|
||||
//server and tagged server should be resolved as the same instance
|
||||
@@ -347,8 +400,13 @@ class AutoInjectionTests: XCTestCase {
|
||||
let client = try! container.resolve(tag: "otherTag") as Client
|
||||
|
||||
//then
|
||||
#if swift(>=5.1)
|
||||
let taggedServer = (client as! ClientImp).taggedServer!
|
||||
let nilTaggedServer = (client as! ClientImp).nilTaggedServer!
|
||||
#else
|
||||
let taggedServer = (client as! ClientImp).taggedServer.value!
|
||||
let nilTaggedServer = (client as! ClientImp).nilTaggedServer.value!
|
||||
#endif
|
||||
let server = client.server!
|
||||
|
||||
//server and tagged server should be resolved as different instances
|
||||
@@ -359,19 +417,89 @@ class AutoInjectionTests: XCTestCase {
|
||||
XCTAssertNotNil(taggedServer)
|
||||
XCTAssertNotNil(nilTaggedServer)
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct Foo
|
||||
{
|
||||
struct Bar
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
struct Baz
|
||||
{
|
||||
struct Bar
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func testScopedTypes() {
|
||||
let key1 = DefinitionKey(type: Baz.Bar.self, typeOfArguments: Void.self)
|
||||
let key2 = DefinitionKey(type: Foo.Bar.self, typeOfArguments: Void.self)
|
||||
|
||||
XCTAssertNotEqual(key1, key2)
|
||||
XCTAssertNotEqual(key1.hashValue, key2.hashValue)
|
||||
|
||||
container.register { Baz.Bar() }
|
||||
|
||||
XCTAssertNotNil(try? container.resolve() as Baz.Bar)
|
||||
XCTAssertThrowsError(try container.resolve() as Foo.Bar)
|
||||
|
||||
container.register { Foo.Bar() }
|
||||
|
||||
XCTAssertNotNil(try? container.resolve() as Foo.Bar)
|
||||
}
|
||||
|
||||
func testThatItAutoInjectsPropertyWithCollaboratingContainer() {
|
||||
let collaborator = DependencyContainer()
|
||||
collaborator.register { ServerImp() as Server }
|
||||
container.register { ClientImp() as Client }
|
||||
|
||||
|
||||
container.collaborate(with: collaborator)
|
||||
collaborator.collaborate(with: container)
|
||||
|
||||
|
||||
let client = try! container.resolve() as Client
|
||||
let server = client.server
|
||||
XCTAssertTrue(client === server?.client)
|
||||
}
|
||||
|
||||
|
||||
func testThatItDoesNotAutoInjectIfDisabledInDefinition() {
|
||||
container.register { ServerImp() as Server }
|
||||
container.register { ClientImp() as Client }
|
||||
.autoInjectingProperties(false)
|
||||
|
||||
let client = try! container.resolve() as Client
|
||||
let server = client.server
|
||||
|
||||
XCTAssertNil(server)
|
||||
}
|
||||
|
||||
func testThatItDoesNotAutoInjectIfDisabledInContainer() {
|
||||
let container = DependencyContainer(autoInjectProperties: false)
|
||||
container.register { ServerImp() as Server }
|
||||
container.register { ClientImp() as Client }
|
||||
|
||||
let client = try! container.resolve() as Client
|
||||
let server = client.server
|
||||
|
||||
XCTAssertNil(server)
|
||||
}
|
||||
|
||||
func testThatItAutoInjectsWhenOverridenInDefinition() {
|
||||
let container = DependencyContainer(autoInjectProperties: false)
|
||||
container.register { ServerImp() as Server }
|
||||
container.register { ClientImp() as Client }
|
||||
.autoInjectingProperties(true)
|
||||
|
||||
let client = try! container.resolve() as Client
|
||||
let server = client.server
|
||||
|
||||
XCTAssertNotNil(server)
|
||||
XCTAssertNil(server?.client)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -50,30 +50,6 @@ class AutoWiringTests: XCTestCase {
|
||||
|
||||
let container = DependencyContainer()
|
||||
|
||||
static var allTests = {
|
||||
return [
|
||||
("testThatItCanResolveWithAutoWiring", testThatItCanResolveWithAutoWiring),
|
||||
("testThatItUsesAutoWireFactoryWithMostNumberOfArguments", testThatItUsesAutoWireFactoryWithMostNumberOfArguments),
|
||||
("testThatItThrowsAmbiguityErrorWhenUsingAutoWire", testThatItThrowsAmbiguityErrorWhenUsingAutoWire),
|
||||
("testThatItUsesAutoWireFactoryWithMostNumberOfArguments", testThatItUsesAutoWireFactoryWithMostNumberOfArguments),
|
||||
("testThatItPrefersTaggedFactoryWithDifferentNumberOfArgumentsWhenUsingAutoWire", testThatItPrefersTaggedFactoryWithDifferentNumberOfArgumentsWhenUsingAutoWire),
|
||||
("testThatItPrefersTaggedFactoryWithDifferentTypesOfArgumentsWhenUsingAutoWire", testThatItPrefersTaggedFactoryWithDifferentTypesOfArgumentsWhenUsingAutoWire),
|
||||
("testThatItFallbackToNotTaggedFactoryWhenUsingAutoWire", testThatItFallbackToNotTaggedFactoryWhenUsingAutoWire),
|
||||
("testThatItDoesNotTryToUseAutoWiringWhenCallingResolveWithArguments", testThatItDoesNotTryToUseAutoWiringWhenCallingResolveWithArguments),
|
||||
("testThatItDoesNotUseAutoWiringWhenFailedToResolveLowLevelDependency", testThatItDoesNotUseAutoWiringWhenFailedToResolveLowLevelDependency),
|
||||
("testThatItReusesInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgain", testThatItReusesInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgain),
|
||||
("testThatItReusesInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgainWithTheSameTag", testThatItReusesInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgainWithTheSameTag),
|
||||
("testThatItDoesNotReuseInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgainWithAnotherTag", testThatItDoesNotReuseInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgainWithAnotherTag),
|
||||
("testThatItUsesTagToResolveDependenciesWithAutoWiringWith1Argument", testThatItUsesTagToResolveDependenciesWithAutoWiringWith1Argument),
|
||||
("testThatItUsesTagToResolveDependenciesWithAutoWiringWith2Arguments", testThatItUsesTagToResolveDependenciesWithAutoWiringWith2Arguments),
|
||||
("testThatItUsesTagToResolveDependenciesWithAutoWiringWith3Arguments", testThatItUsesTagToResolveDependenciesWithAutoWiringWith3Arguments),
|
||||
("testThatItUsesTagToResolveDependenciesWithAutoWiringWith4Arguments", testThatItUsesTagToResolveDependenciesWithAutoWiringWith4Arguments),
|
||||
("testThatItUsesTagToResolveDependenciesWithAutoWiringWith5Arguments", testThatItUsesTagToResolveDependenciesWithAutoWiringWith5Arguments),
|
||||
("testThatItUsesTagToResolveDependenciesWithAutoWiringWith6Arguments", testThatItUsesTagToResolveDependenciesWithAutoWiringWith6Arguments),
|
||||
("testThatItCanAutoWireOptional", testThatItCanAutoWireOptional)
|
||||
]
|
||||
}()
|
||||
|
||||
override func setUp() {
|
||||
container.reset()
|
||||
}
|
||||
@@ -138,12 +114,10 @@ class AutoWiringTests: XCTestCase {
|
||||
container.register { ServiceImp2() }
|
||||
|
||||
//when
|
||||
AssertThrows(expression: try container.resolve() as AutoWiredClient) { error -> Bool in
|
||||
switch error {
|
||||
case let DipError.autoWiringFailed(_, error):
|
||||
if case DipError.ambiguousDefinitions = error { return true }
|
||||
else { return false }
|
||||
default: return false
|
||||
XCTAssertThrowsError(try self.container.resolve() as AutoWiredClient) { (error) in
|
||||
guard case DipError.autoWiringFailed(_, DipError.ambiguousDefinitions) = error else {
|
||||
XCTFail("Thrown unexpected error: \(error)")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -233,8 +207,12 @@ class AutoWiringTests: XCTestCase {
|
||||
|
||||
//when
|
||||
let service = try! container.resolve() as Service
|
||||
AssertThrows(expression: try container.resolve(arguments: service) as AutoWiredClient,
|
||||
"Container should not use auto-wiring when resolving with runtime arguments")
|
||||
|
||||
// then
|
||||
XCTAssertThrowsError(
|
||||
try self.container.resolve(arguments: service) as AutoWiredClient,
|
||||
"Container should not use auto-wiring when resolving with runtime arguments"
|
||||
)
|
||||
}
|
||||
|
||||
func testThatItDoesNotUseAutoWiringWhenFailedToResolveLowLevelDependency() {
|
||||
@@ -259,12 +237,13 @@ class AutoWiringTests: XCTestCase {
|
||||
container.register { ServiceImp2() }
|
||||
|
||||
//then
|
||||
AssertThrows(expression: try container.resolve() as AutoWiredClient,
|
||||
"Container should not use auto-wiring when definition for resolved type is registered.")
|
||||
XCTAssertThrowsError(
|
||||
try self.container.resolve() as AutoWiredClient,
|
||||
"Container should not use auto-wiring when definition for resolved type is registered."
|
||||
)
|
||||
}
|
||||
|
||||
func testThatItReusesInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgain() {
|
||||
|
||||
//given
|
||||
container.register { ServiceImp1() as Service }
|
||||
container.register { ServiceImp2() }
|
||||
@@ -282,8 +261,10 @@ class AutoWiringTests: XCTestCase {
|
||||
let resolved = try! container.resolve() as AutoWiredClient
|
||||
|
||||
//then
|
||||
//when doing another auto-wiring during resolve we should reuse instance
|
||||
XCTAssertTrue((resolved as! AutoWiredClientImp) === (anotherInstance as! AutoWiredClientImp))
|
||||
XCTAssertTrue(
|
||||
(resolved as! AutoWiredClientImp) === (anotherInstance as! AutoWiredClientImp),
|
||||
"when doing another auto-wiring during resolve we should reuse instance"
|
||||
)
|
||||
}
|
||||
|
||||
func testThatItReusesInstancesResolvedWithoutAutoWiringWhenUsingAutoWiringAgain() {
|
||||
@@ -307,8 +288,10 @@ class AutoWiringTests: XCTestCase {
|
||||
let resolved = try! container.resolve(arguments: service1, service2) as AutoWiredClient
|
||||
|
||||
//then
|
||||
//when doing another auto-wiring during resolve we should reuse instance
|
||||
XCTAssertTrue((resolved as! AutoWiredClientImp) === (anotherInstance as! AutoWiredClientImp))
|
||||
XCTAssertTrue(
|
||||
(resolved as! AutoWiredClientImp) === (anotherInstance as! AutoWiredClientImp),
|
||||
"when doing another auto-wiring during resolve we should reuse instance"
|
||||
)
|
||||
}
|
||||
|
||||
func testThatItReusesInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgainWithTheSameTag() {
|
||||
@@ -330,8 +313,10 @@ class AutoWiringTests: XCTestCase {
|
||||
let resolved = try! container.resolve(tag: "tag") as AutoWiredClient
|
||||
|
||||
//then
|
||||
//when doing another auto-wiring during resolve we should reuse instance
|
||||
XCTAssertTrue((resolved as! AutoWiredClientImp) === (anotherInstance as! AutoWiredClientImp))
|
||||
XCTAssertTrue(
|
||||
(resolved as! AutoWiredClientImp) === (anotherInstance as! AutoWiredClientImp),
|
||||
"when doing another auto-wiring during resolve we should reuse instance"
|
||||
)
|
||||
}
|
||||
|
||||
func testThatItDoesNotReuseInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgainWithAnotherTag() {
|
||||
@@ -353,8 +338,10 @@ class AutoWiringTests: XCTestCase {
|
||||
let resolved = try! container.resolve(tag: "tag") as AutoWiredClient
|
||||
|
||||
//then
|
||||
//when doing another auto-wiring during resolve we should reuse instance
|
||||
XCTAssertTrue((resolved as! AutoWiredClientImp) !== (anotherInstance as! AutoWiredClientImp))
|
||||
XCTAssertTrue(
|
||||
(resolved as! AutoWiredClientImp) !== (anotherInstance as! AutoWiredClientImp),
|
||||
"when doing another auto-wiring during resolve we should reuse instance"
|
||||
)
|
||||
}
|
||||
|
||||
func testThatItUsesTagToResolveDependenciesWithAutoWiringWith1Argument() {
|
||||
@@ -464,19 +451,11 @@ class AutoWiringTests: XCTestCase {
|
||||
|
||||
var resolved: AutoWiredClient?
|
||||
//when
|
||||
AssertNoThrow(expression: resolved = try container.resolve() as AutoWiredClient?)
|
||||
XCTAssertNoThrow(resolved = try self.container.resolve() as AutoWiredClient?)
|
||||
XCTAssertNotNil(resolved)
|
||||
|
||||
//when
|
||||
AssertNoThrow(expression: resolved = try container.resolve() as AutoWiredClient!)
|
||||
XCTAssertNotNil(resolved)
|
||||
|
||||
//when
|
||||
AssertNoThrow(expression: resolved = try container.resolve(tag: "tag") as AutoWiredClient?)
|
||||
XCTAssertNotNil(resolved)
|
||||
|
||||
//when
|
||||
AssertNoThrow(expression: resolved = try container.resolve(tag: "tag") as AutoWiredClient!)
|
||||
XCTAssertNoThrow(resolved = try self.container.resolve(tag: "tag") as AutoWiredClient?)
|
||||
XCTAssertNotNil(resolved)
|
||||
}
|
||||
|
||||
|
||||
@@ -47,27 +47,6 @@ class ComponentScopeTests: XCTestCase {
|
||||
|
||||
let container = DependencyContainer()
|
||||
|
||||
static var allTests = {
|
||||
return [
|
||||
("testThatSharedIsDefaultScope", testThatSharedIsDefaultScope),
|
||||
("testThatScopeCanBeChanged", testThatScopeCanBeChanged),
|
||||
("testThatItResolvesTypeAsNewInstanceForUniqueScope", testThatItResolvesTypeAsNewInstanceForUniqueScope),
|
||||
("testThatItReusesInstanceForSingletonScope", testThatItReusesInstanceForSingletonScope),
|
||||
("testThatSingletonIsNotReusedAcrossContainers", testThatSingletonIsNotReusedAcrossContainers),
|
||||
("testThatSingletonIsReleasedWhenDefinitionIsRemoved", testThatSingletonIsReleasedWhenDefinitionIsRemoved),
|
||||
("testThatSingletonIsReleasedWhenDefinitionIsOverridden", testThatSingletonIsReleasedWhenDefinitionIsOverridden),
|
||||
("testThatSingletonIsReleasedWhenContainerIsReset", testThatSingletonIsReleasedWhenContainerIsReset),
|
||||
("testThatItReusesInstanceInSharedScopeDuringResolve", testThatItReusesInstanceInSharedScopeDuringResolve),
|
||||
("testThatItDoesNotReuseInstanceInSharedScopeInNextResolve", testThatItDoesNotReuseInstanceInSharedScopeInNextResolve),
|
||||
("testThatItDoesNotReuseInstanceInSharedScopeResolvedForNilTag", testThatItDoesNotReuseInstanceInSharedScopeResolvedForNilTagWhenResolvingForAnotherTag),
|
||||
("testThatItReusesInstanceInSharedScopeResolvedForNilTag", testThatItReusesInstanceInSharedScopeResolvedForNilTag),
|
||||
("testThatItReusesResolvedInstanceWhenResolvingOptional", testThatItReusesResolvedInstanceWhenResolvingOptional),
|
||||
("testThatItHoldsWeakReferenceToWeakSingletonInstance", testThatItHoldsWeakReferenceToWeakSingletonInstance),
|
||||
("testThatItResolvesWeakSingletonAgainAfterItWasReleased", testThatItResolvesWeakSingletonAgainAfterItWasReleased),
|
||||
("testThatCollaboratingContainersReuseSingletonsResolvedByAnotherContainer", testThatCollaboratingContainersReuseSingletonsResolvedByAnotherContainer)
|
||||
]
|
||||
}()
|
||||
|
||||
override func setUp() {
|
||||
container.reset()
|
||||
}
|
||||
@@ -301,23 +280,17 @@ class ComponentScopeTests: XCTestCase {
|
||||
|
||||
func testThatItReusesResolvedInstanceWhenResolvingOptional() {
|
||||
var otherService: Service!
|
||||
var impOtherService: Service!
|
||||
var anyOtherService: Any!
|
||||
var anyImpOtherService: Any!
|
||||
|
||||
|
||||
container.register { ServiceImp1() as Service }
|
||||
.resolvingProperties { container, service in
|
||||
otherService = try! container.resolve() as Service?
|
||||
impOtherService = try! container.resolve() as Service!
|
||||
anyOtherService = try! container.resolve((Service?).self)
|
||||
anyImpOtherService = try! container.resolve((Service!).self)
|
||||
}
|
||||
|
||||
let service = try! container.resolve() as Service
|
||||
XCTAssertTrue(otherService as! ServiceImp1 === service as! ServiceImp1)
|
||||
XCTAssertTrue(impOtherService as! ServiceImp1 === service as! ServiceImp1)
|
||||
XCTAssertTrue(anyOtherService as! ServiceImp1 === service as! ServiceImp1)
|
||||
XCTAssertTrue(anyImpOtherService as! ServiceImp1 === service as! ServiceImp1)
|
||||
}
|
||||
|
||||
func testThatItHoldsWeakReferenceToWeakSingletonInstance() {
|
||||
@@ -347,7 +320,10 @@ class ComponentScopeTests: XCTestCase {
|
||||
_ = try? container.resolve() as ServiceImp1
|
||||
|
||||
//then
|
||||
AssertNoThrow(expression: try container.resolve() as Service, "Weak singleton should be resolved again.")
|
||||
XCTAssertNoThrow(
|
||||
try container.resolve() as Service,
|
||||
"Weak singleton should be resolved again."
|
||||
)
|
||||
}
|
||||
|
||||
func testThatCollaboratingContainersReuseSingletonsResolvedByAnotherContainer() {
|
||||
|
||||
@@ -39,20 +39,6 @@ class ContextTests: XCTestCase {
|
||||
|
||||
let container = DependencyContainer()
|
||||
|
||||
static var allTests = {
|
||||
return [
|
||||
("testThatContextStoresCurrentlyResolvedType", testThatContextStoresCurrentlyResolvedType),
|
||||
("testThatContextStoresInjectedInType", testThatContextStoresInjectedInType),
|
||||
("testThatContextStoresTheTagPassedToResolve", testThatContextStoresTheTagPassedToResolve),
|
||||
("testThatContextStoresTheTagPassedToResolveWhenAutoInjecting", testThatContextStoresTheTagPassedToResolveWhenAutoInjecting),
|
||||
("testThatContextStoresTheTagPassedToResolveWhenAutoWiring", testThatContextStoresTheTagPassedToResolveWhenAutoWiring),
|
||||
("testThatContextDoesNotOverrideNilTagPassedToResolve", testThatContextDoesNotOverrideNilTagPassedToResolve),
|
||||
("testThatContextStoresNameOfAutoInjectedProperty", testThatContextStoresNameOfAutoInjectedProperty),
|
||||
("testThatItDoesNotSetInjectedInTypeWhenResolvingWithCollaboration", testThatItDoesNotSetInjectedInTypeWhenResolvingWithCollaboration),
|
||||
("testThatContextIsPreservedWhenResolvingWithCollaboration", testThatContextIsPreservedWhenResolvingWithCollaboration)
|
||||
]
|
||||
}()
|
||||
|
||||
override func setUp() {
|
||||
container.reset()
|
||||
container.register { ServiceImp2() }
|
||||
|
||||
@@ -36,18 +36,6 @@ class DefinitionTests: XCTestCase {
|
||||
let tag1 = DependencyContainer.Tag.String("tag1")
|
||||
let tag2 = DependencyContainer.Tag.String("tag2")
|
||||
|
||||
static var allTests = {
|
||||
return [
|
||||
("testThatDefinitionKeyIsEqualBy_Type_Factory_Tag", testThatDefinitionKeyIsEqualBy_Type_Factory_Tag),
|
||||
("testThatDefinitionKeysWithDifferentTypesAreNotEqual", testThatDefinitionKeysWithDifferentTypesAreNotEqual),
|
||||
("testThatDefinitionKeysWithDifferentFactoriesAreNotEqual", testThatDefinitionKeysWithDifferentFactoriesAreNotEqual),
|
||||
("testThatDefinitionKeysWithDifferentTagsAreNotEqual", testThatDefinitionKeysWithDifferentTagsAreNotEqual),
|
||||
("testThatResolveDependenciesCallsResolveDependenciesBlock", testThatResolveDependenciesCallsResolveDependenciesBlock),
|
||||
("testThatResolveDependenciesBlockIsNotCalledWhenPassedWrongInstance", testThatResolveDependenciesBlockIsNotCalledWhenPassedWrongInstance),
|
||||
("testThatItRegisteresOptionalTypesAsForwardedTypes", testThatItRegisteresOptionalTypesAsForwardedTypes)
|
||||
]
|
||||
}()
|
||||
|
||||
func testThatDefinitionKeyIsEqualBy_Type_Factory_Tag() {
|
||||
let equalKey1 = DefinitionKey(type: Service.self, typeOfArguments: F1.self, tag: tag1)
|
||||
let equalKey2 = DefinitionKey(type: Service.self, typeOfArguments: F1.self, tag: tag1)
|
||||
@@ -116,7 +104,6 @@ class DefinitionTests: XCTestCase {
|
||||
let def = Definition<Service, ()>(scope: .unique) { ServiceImp() as Service }
|
||||
|
||||
XCTAssertTrue(def.implementingTypes.contains(where: { $0 == Service?.self }))
|
||||
XCTAssertTrue(def.implementingTypes.contains(where: { $0 == Service!.self }))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+112
-116
@@ -30,7 +30,7 @@ private class ServiceImp1: Service { }
|
||||
private class ServiceImp2: Service { }
|
||||
|
||||
private protocol Server: class {
|
||||
weak var client: Client! { get }
|
||||
var client: Client! { get }
|
||||
}
|
||||
private protocol Client: class {
|
||||
var server: Server! { get }
|
||||
@@ -49,31 +49,6 @@ class DipTests: XCTestCase {
|
||||
|
||||
let container = DependencyContainer()
|
||||
|
||||
static var allTests = {
|
||||
return [
|
||||
("testThatCreatingContainerWithConfigBlockDoesNotCreateRetainCycle", testThatCreatingContainerWithConfigBlockDoesNotCreateRetainCycle),
|
||||
("testThatItResolvesInstanceRegisteredWithoutTag", testThatItResolvesInstanceRegisteredWithoutTag),
|
||||
("testThatItResolvesInstanceRegisteredWithTag", testThatItResolvesInstanceRegisteredWithTag),
|
||||
("testThatItResolvesDifferentInstancesRegisteredForDifferentTags", testThatItResolvesDifferentInstancesRegisteredForDifferentTags),
|
||||
("testThatNewRegistrationOverridesPreviousRegistration", testThatNewRegistrationOverridesPreviousRegistration),
|
||||
("testThatItCallsResolveDependenciesOnDefinition", testThatItCallsResolveDependenciesOnDefinition),
|
||||
("testThatItThrowsErrorIfCanNotFindDefinitionForType", testThatItThrowsErrorIfCanNotFindDefinitionForType),
|
||||
("testThatItThrowsErrorIfCanNotFindDefinitionForTag", testThatItThrowsErrorIfCanNotFindDefinitionForTag),
|
||||
("testThatItThrowsErrorIfCanNotFindDefinitionForFactoryWithArguments", testThatItThrowsErrorIfCanNotFindDefinitionForFactoryWithArguments),
|
||||
("testThatItThrowsErrorIfConstructorThrows", testThatItThrowsErrorIfConstructorThrows),
|
||||
("testThatItThrowsErrorIfFailsToResolveDependency", testThatItThrowsErrorIfFailsToResolveDependency),
|
||||
("testThatItCallsDidResolveDependenciesOnResolvableIntance", testThatItCallsDidResolveDependenciesOnResolvableIntance),
|
||||
("testThatItCallsDidResolveDependenciesInReverseOrder", testThatItCallsDidResolveDependenciesInReverseOrder),
|
||||
("testItCallsResolveDependenciesOnResolableInstance", testItCallsResolveDependenciesOnResolableInstance),
|
||||
("testThatItResolvesCircularDependencies", testThatItResolvesCircularDependencies),
|
||||
("testThatItCanResolveUsingContainersCollaboration", testThatItCanResolveUsingContainersCollaboration),
|
||||
("testThatCollaboratingWithSelfIsIgnored", testThatCollaboratingWithSelfIsIgnored),
|
||||
("testThatCollaboratingContainersAreWeakReferences", testThatCollaboratingContainersAreWeakReferences),
|
||||
("testThatCollaboratingContainersReuseInstancesResolvedByAnotherContainer", testThatCollaboratingContainersReuseInstancesResolvedByAnotherContainer),
|
||||
("testThatItCanHandleSeparateContainersAndTheirCollaboration", testThatItCanHandleSeparateContainersAndTheirCollaboration)
|
||||
]
|
||||
}()
|
||||
|
||||
override func setUp() {
|
||||
container.reset()
|
||||
}
|
||||
@@ -124,12 +99,6 @@ class DipTests: XCTestCase {
|
||||
|
||||
//then
|
||||
XCTAssertTrue(optService is ServiceImp1)
|
||||
|
||||
//and when
|
||||
let impService = try! container.resolve((Service!).self)
|
||||
|
||||
//then
|
||||
XCTAssertTrue(impService is ServiceImp1)
|
||||
}
|
||||
|
||||
func testThatItResolvesInstanceRegisteredWithTag() {
|
||||
@@ -153,12 +122,6 @@ class DipTests: XCTestCase {
|
||||
|
||||
//then
|
||||
XCTAssertTrue(optService is ServiceImp1)
|
||||
|
||||
//and when
|
||||
let impService = try! container.resolve((Service!).self, tag: "service")
|
||||
|
||||
//then
|
||||
XCTAssertTrue(impService is ServiceImp1)
|
||||
}
|
||||
|
||||
func testThatItResolvesDifferentInstancesRegisteredForDifferentTags() {
|
||||
@@ -189,14 +152,6 @@ class DipTests: XCTestCase {
|
||||
//then
|
||||
XCTAssertTrue(optService1 is ServiceImp1)
|
||||
XCTAssertTrue(optService2 is ServiceImp2)
|
||||
|
||||
//and when
|
||||
let impService1 = try! container.resolve((Service!).self, tag: "service1")
|
||||
let impService2 = try! container.resolve((Service!).self, tag: "service2")
|
||||
|
||||
//then
|
||||
XCTAssertTrue(impService1 is ServiceImp1)
|
||||
XCTAssertTrue(impService2 is ServiceImp2)
|
||||
}
|
||||
|
||||
func testThatNewRegistrationOverridesPreviousRegistration() {
|
||||
@@ -242,38 +197,34 @@ class DipTests: XCTestCase {
|
||||
XCTAssertTrue(resolveDependenciesCalled)
|
||||
|
||||
resolveDependenciesCalled = false
|
||||
|
||||
//and when
|
||||
let _ = try! container.resolve((Service!).self)
|
||||
|
||||
//then
|
||||
XCTAssertTrue(resolveDependenciesCalled)
|
||||
}
|
||||
|
||||
|
||||
func testThatItThrowsErrorIfCanNotFindDefinitionForType() {
|
||||
//given
|
||||
container.register { ServiceImp1() as ServiceImp1 }
|
||||
|
||||
//when
|
||||
AssertThrows(expression: try container.resolve() as Service) { error in
|
||||
guard case let DipError.definitionNotFound(key) = error else { return false }
|
||||
XCTAssertThrowsError(try self.container.resolve() as Service) { error in
|
||||
guard case let DipError.definitionNotFound(key) = error else {
|
||||
XCTFail("Thrown unexpected error: \(error)")
|
||||
return
|
||||
}
|
||||
|
||||
//then
|
||||
let expectedKey = DefinitionKey(type: Service.self, typeOfArguments: Void.self, tag: nil)
|
||||
XCTAssertEqual(key, expectedKey)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
//and when
|
||||
AssertThrows(expression: try container.resolve(Service.self)) { error in
|
||||
guard case let DipError.definitionNotFound(key) = error else { return false }
|
||||
XCTAssertThrowsError(try self.container.resolve(Service.self)) { error in
|
||||
guard case let DipError.definitionNotFound(key) = error else {
|
||||
XCTFail("Thrown unexpected error: \(error)")
|
||||
return
|
||||
}
|
||||
|
||||
//then
|
||||
let expectedKey = DefinitionKey(type: Service.self, typeOfArguments: Void.self, tag: nil)
|
||||
XCTAssertEqual(key, expectedKey)
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,25 +233,27 @@ class DipTests: XCTestCase {
|
||||
container.register(tag: "some tag") { ServiceImp1() as Service }
|
||||
|
||||
//when
|
||||
AssertThrows(expression: try container.resolve(tag: "other tag") as Service) { error in
|
||||
guard case let DipError.definitionNotFound(key) = error else { return false }
|
||||
XCTAssertThrowsError(try self.container.resolve(tag: "other tag") as Service) { error in
|
||||
guard case let DipError.definitionNotFound(key) = error else {
|
||||
XCTFail("Thrown unexpected error: \(error)")
|
||||
return
|
||||
}
|
||||
|
||||
//then
|
||||
let expectedKey = DefinitionKey(type: Service.self, typeOfArguments: Void.self, tag: "other tag")
|
||||
XCTAssertEqual(key, expectedKey)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
//and when
|
||||
AssertThrows(expression: try container.resolve(Service.self, tag: "other tag")) { error in
|
||||
guard case let DipError.definitionNotFound(key) = error else { return false }
|
||||
XCTAssertThrowsError(try self.container.resolve(Service.self, tag: "other tag")) { error in
|
||||
guard case let DipError.definitionNotFound(key) = error else {
|
||||
XCTFail("Thrown unexpected error: \(error)")
|
||||
return
|
||||
}
|
||||
|
||||
//then
|
||||
let expectedKey = DefinitionKey(type: Service.self, typeOfArguments: Void.self, tag: "other tag")
|
||||
XCTAssertEqual(key, expectedKey)
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,25 +262,27 @@ class DipTests: XCTestCase {
|
||||
container.register { ServiceImp1() as Service }
|
||||
|
||||
//when
|
||||
AssertThrows(expression: try container.resolve(arguments: "some string") as Service) { error in
|
||||
guard case let DipError.definitionNotFound(key) = error else { return false }
|
||||
XCTAssertThrowsError(try self.container.resolve(arguments: "some string") as Service) { error in
|
||||
guard case let DipError.definitionNotFound(key) = error else {
|
||||
XCTFail("Thrown unexpected error: \(error)")
|
||||
return
|
||||
}
|
||||
|
||||
//then
|
||||
let expectedKey = DefinitionKey(type: Service.self, typeOfArguments: String.self, tag: nil)
|
||||
XCTAssertEqual(key, expectedKey)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
//and when
|
||||
AssertThrows(expression: try container.resolve(Service.self, arguments: "some string")) { error in
|
||||
guard case let DipError.definitionNotFound(key) = error else { return false }
|
||||
XCTAssertThrowsError(try self.container.resolve(Service.self, arguments: "some string")) { error in
|
||||
guard case let DipError.definitionNotFound(key) = error else {
|
||||
XCTFail("Thrown unexpected error: \(error)")
|
||||
return
|
||||
}
|
||||
|
||||
//then
|
||||
let expectedKey = DefinitionKey(type: Service.self, typeOfArguments: String.self, tag: nil)
|
||||
XCTAssertEqual(key, expectedKey)
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,18 +293,18 @@ class DipTests: XCTestCase {
|
||||
container.register { () throws -> Service in throw expectedError }
|
||||
|
||||
//when
|
||||
AssertThrows(expression: try container.resolve() as Service) { error in
|
||||
switch error {
|
||||
case let DipError.definitionNotFound(key) where key == failedKey: return true
|
||||
default: return false
|
||||
XCTAssertThrowsError(try self.container.resolve() as Service) { error in
|
||||
guard case let DipError.definitionNotFound(key) = error, key == failedKey else {
|
||||
XCTFail("Thrown unexpected error: \(error)")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
//and when
|
||||
AssertThrows(expression: try container.resolve(Service.self)) { error in
|
||||
switch error {
|
||||
case let DipError.definitionNotFound(key) where key == failedKey: return true
|
||||
default: return false
|
||||
XCTAssertThrowsError(try self.container.resolve(Service.self)) { error in
|
||||
guard case let DipError.definitionNotFound(key) = error, key == failedKey else {
|
||||
XCTFail("Thrown unexpected error: \(error)")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -365,18 +320,18 @@ class DipTests: XCTestCase {
|
||||
}
|
||||
|
||||
//when
|
||||
AssertThrows(expression: try container.resolve() as Service) { error in
|
||||
switch error {
|
||||
case let DipError.definitionNotFound(key) where key == failedKey: return true
|
||||
default: return false
|
||||
XCTAssertThrowsError(try self.container.resolve() as Service) { error in
|
||||
guard case let DipError.definitionNotFound(key) = error, key == failedKey else {
|
||||
XCTFail("Thrown unexpected error: \(error)")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
//and when
|
||||
AssertThrows(expression: try container.resolve(Service.self)) { error in
|
||||
switch error {
|
||||
case let DipError.definitionNotFound(key) where key == failedKey: return true
|
||||
default: return false
|
||||
XCTAssertThrowsError(try self.container.resolve(Service.self)) { error in
|
||||
guard case let DipError.definitionNotFound(key) = error, key == failedKey else {
|
||||
XCTFail("Thrown unexpected error: \(error)")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -521,22 +476,15 @@ class DipTests: XCTestCase {
|
||||
XCTAssertNotNil(self.server?.client)
|
||||
XCTAssertNotNil(self.secondServer?.client)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//given
|
||||
container.register { try ResolvableServer(client: self.container.resolve()) as Server }
|
||||
.resolvingProperties { (container: DependencyContainer, server: Server) in
|
||||
let server = server as! ResolvableServer
|
||||
server.secondClient = try container.resolve() as Client
|
||||
}
|
||||
.resolvingProperty(\ResolvableServer.secondClient, as: Client.self)
|
||||
|
||||
container.register { ResolvableClient() as Client }
|
||||
.resolvingProperties { (container: DependencyContainer, client: Client) in
|
||||
let client = client as! ResolvableClient
|
||||
client.server = try container.resolve() as Server
|
||||
client.secondServer = try container.resolve() as Server
|
||||
}
|
||||
.resolvingProperty(\ResolvableClient.server, factory: { try $0.resolve() })
|
||||
.resolvingProperty(\ResolvableClient.secondServer)
|
||||
|
||||
//when
|
||||
let client = (try! container.resolve() as Client) as! ResolvableClient
|
||||
@@ -584,7 +532,7 @@ class DipTests: XCTestCase {
|
||||
}
|
||||
|
||||
//then
|
||||
AssertNoThrow(expression: try container.validate("arg"))
|
||||
XCTAssertNoThrow(try self.container.validate("arg"))
|
||||
XCTAssertTrue(createdService1)
|
||||
XCTAssertTrue(createdService2)
|
||||
XCTAssertTrue(createdService3)
|
||||
@@ -607,8 +555,8 @@ class DipTests: XCTestCase {
|
||||
}
|
||||
|
||||
//then
|
||||
AssertNoThrow(expression:
|
||||
try container.validate(
|
||||
XCTAssertNoThrow(
|
||||
try self.container.validate(
|
||||
"1",
|
||||
expectedIntArgument,
|
||||
"x",
|
||||
@@ -623,8 +571,18 @@ class DipTests: XCTestCase {
|
||||
container.register { (a: Int) -> Service in ServiceImp1() as Service }
|
||||
|
||||
//then
|
||||
AssertThrows(expression: try container.validate()) { error in error is DipError }
|
||||
AssertThrows(expression: try container.validate("1")) { error in error is DipError }
|
||||
XCTAssertThrowsError(try self.container.validate()) { error in
|
||||
guard error is DipError else {
|
||||
XCTFail("Thrown unexpected error: \(error)")
|
||||
return
|
||||
}
|
||||
}
|
||||
XCTAssertThrowsError(try self.container.validate("1")) { error in
|
||||
guard error is DipError else {
|
||||
XCTFail("Thrown unexpected error: \(error)")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testThatItFailsValidationOnlyForDipErrors() {
|
||||
@@ -636,7 +594,7 @@ class DipTests: XCTestCase {
|
||||
}
|
||||
|
||||
//then
|
||||
AssertNoThrow(expression: try container.validate())
|
||||
XCTAssertNoThrow(try self.container.validate())
|
||||
|
||||
//given
|
||||
let key = DefinitionKey(type: Service.self, typeOfArguments: Void.self, tag: nil)
|
||||
@@ -645,9 +603,11 @@ class DipTests: XCTestCase {
|
||||
}
|
||||
|
||||
//then
|
||||
AssertThrows(expression: try container.validate()) { error in
|
||||
if case let DipError.definitionNotFound(_key) = error, _key == key { return true }
|
||||
else { return false }
|
||||
XCTAssertThrowsError(try self.container.validate()) { error in
|
||||
guard case let DipError.definitionNotFound(_key) = error, _key == key else {
|
||||
XCTFail("Thrown unexpected error: \(error)")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -665,10 +625,10 @@ extension DipTests {
|
||||
container.collaborate(with: collaborator)
|
||||
|
||||
//then
|
||||
AssertNoThrow(expression: try container.resolve() as Service)
|
||||
AssertNoThrow(expression: try container.resolve(Service.self))
|
||||
AssertNoThrow(expression: try collaborator.resolve() as String)
|
||||
AssertNoThrow(expression: try collaborator.resolve(String.self))
|
||||
XCTAssertNoThrow(try self.container.resolve() as Service)
|
||||
XCTAssertNoThrow(try self.container.resolve(Service.self))
|
||||
XCTAssertNoThrow(try collaborator.resolve() as String)
|
||||
XCTAssertNoThrow(try collaborator.resolve(String.self))
|
||||
}
|
||||
|
||||
func testThatCollaboratingWithSelfIsIgnored() {
|
||||
@@ -882,3 +842,39 @@ extension DipTests {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
extension DipTests {
|
||||
// https://bugs.swift.org/browse/SR-8878
|
||||
func test_weak_mirror_regression() {
|
||||
class A {
|
||||
static var released = false
|
||||
deinit {
|
||||
A.released = true
|
||||
}
|
||||
}
|
||||
class B {
|
||||
static var released = false
|
||||
weak var a: A?
|
||||
init(a: A) {
|
||||
self.a = a
|
||||
}
|
||||
deinit {
|
||||
B.released = true
|
||||
}
|
||||
}
|
||||
let container = DependencyContainer()
|
||||
let tag = "my_tag"
|
||||
container.register(.unique, tag: tag, factory: B.init(a:))
|
||||
do {
|
||||
let a0 = A()
|
||||
let _: B = try container.resolve(tag: tag, arguments: a0)
|
||||
|
||||
|
||||
XCTAssertTrue(B.released)
|
||||
// Due to regression in swift 4.2 Mirror retains weak children
|
||||
// https://bugs.swift.org/browse/SR-8878
|
||||
XCTAssertFalse(A.released)
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,252 @@
|
||||
//
|
||||
// DipUI
|
||||
//
|
||||
// Copyright (c) 2016 Ilya Puchka <ilyapuchka@gmail.com>
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#if (canImport(UIKit) || canImport(AppKit)) && !SWIFT_PACKAGE
|
||||
|
||||
import XCTest
|
||||
@testable import Dip
|
||||
|
||||
#if canImport(UIKit)
|
||||
import UIKit
|
||||
typealias Storyboard = UIStoryboard
|
||||
typealias ViewController = UIViewController
|
||||
typealias StoryboardName = String
|
||||
|
||||
extension UIStoryboard {
|
||||
@nonobjc
|
||||
@discardableResult func instantiateViewControllerWithIdentifier(_ identifier: String) -> UIViewController {
|
||||
return instantiateViewController(withIdentifier: identifier)
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
import AppKit
|
||||
typealias Storyboard = NSStoryboard
|
||||
typealias ViewController = NSViewController
|
||||
typealias StoryboardName = NSStoryboard.Name
|
||||
|
||||
extension NSStoryboard {
|
||||
@discardableResult func instantiateViewControllerWithIdentifier(_ identifier: String) -> NSViewController {
|
||||
return instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(identifier)) as! NSViewController
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if os(iOS)
|
||||
let storyboardName: StoryboardName = "UIStoryboard"
|
||||
#elseif os(tvOS)
|
||||
let storyboardName: StoryboardName = "TVStoryboard"
|
||||
#else
|
||||
let storyboardName: StoryboardName = StoryboardName("NSStoryboard")
|
||||
#endif
|
||||
|
||||
class DipViewController: ViewController, StoryboardInstantiatable {}
|
||||
class NilTagViewController: ViewController, StoryboardInstantiatable {}
|
||||
|
||||
class DipUITests: XCTestCase {
|
||||
|
||||
let storyboard: Storyboard = {
|
||||
let bundle = Bundle(for: DipUITests.self)
|
||||
return Storyboard(name: storyboardName, bundle: bundle)
|
||||
}()
|
||||
|
||||
func testThatViewControllerHasDipTagProperty() {
|
||||
let viewController = storyboard.instantiateViewControllerWithIdentifier("DipViewController")
|
||||
XCTAssertEqual(viewController.dipTag, "vc")
|
||||
}
|
||||
|
||||
func testThatItDoesNotResolveIfContainerIsNotSet() {
|
||||
let container = DependencyContainer()
|
||||
container.register(tag: "vc") { ViewController() }
|
||||
.resolvingProperties { _, _ in
|
||||
XCTFail("Should not resolve when container is not set.")
|
||||
}
|
||||
|
||||
storyboard.instantiateViewControllerWithIdentifier("DipViewController")
|
||||
}
|
||||
|
||||
func testThatItDoesNotResolveIfTagIsNotSet() {
|
||||
let container = DependencyContainer()
|
||||
container.register(tag: "vc") { ViewController() }
|
||||
.resolvingProperties { _, _ in
|
||||
XCTFail("Should not resolve when container is not set.")
|
||||
}
|
||||
|
||||
DependencyContainer.uiContainers = [container]
|
||||
storyboard.instantiateViewControllerWithIdentifier("ViewController")
|
||||
}
|
||||
|
||||
func testThatItResolvesIfContainerAndStringTagAreSet() {
|
||||
var resolved = false
|
||||
let container = DependencyContainer()
|
||||
container.register(storyboardType: DipViewController.self, tag: "vc")
|
||||
.resolvingProperties { _, _ in
|
||||
resolved = true
|
||||
}
|
||||
|
||||
DependencyContainer.uiContainers = [container]
|
||||
storyboard.instantiateViewControllerWithIdentifier("DipViewController")
|
||||
XCTAssertTrue(resolved, "Should resolve when container and tag are set.")
|
||||
}
|
||||
|
||||
func testThatItResolvesIfContainerAndNilTagAreSet() {
|
||||
var resolved = false
|
||||
let container = DependencyContainer()
|
||||
container.register(storyboardType: NilTagViewController.self)
|
||||
.resolvingProperties { _, _ in
|
||||
resolved = true
|
||||
}
|
||||
|
||||
DependencyContainer.uiContainers = [container]
|
||||
storyboard.instantiateViewControllerWithIdentifier("NilTagViewController")
|
||||
XCTAssertTrue(resolved, "Should resolve when container and nil tag are set.")
|
||||
}
|
||||
|
||||
func testThatItDoesNotResolveIfTagDoesNotMatch() {
|
||||
let container = DependencyContainer()
|
||||
container.register(storyboardType: DipViewController.self, tag: "wrong tag")
|
||||
.resolvingProperties { _, _ in
|
||||
XCTFail("Should not resolve when container is not set.")
|
||||
}
|
||||
|
||||
DependencyContainer.uiContainers = [container]
|
||||
storyboard.instantiateViewControllerWithIdentifier("DipViewController")
|
||||
}
|
||||
|
||||
func testThatItResolvesWithDefinitionWithNoTag() {
|
||||
var resolved = false
|
||||
let container = DependencyContainer()
|
||||
container.register(storyboardType: DipViewController.self)
|
||||
.resolvingProperties { _, _ in
|
||||
resolved = true
|
||||
}
|
||||
|
||||
DependencyContainer.uiContainers = [container]
|
||||
storyboard.instantiateViewControllerWithIdentifier("DipViewController")
|
||||
XCTAssertTrue(resolved, "Should fallback to definition with no tag.")
|
||||
}
|
||||
|
||||
func testThatItIteratesUIContainers() {
|
||||
var resolved = false
|
||||
let container1 = DependencyContainer()
|
||||
let container2 = DependencyContainer()
|
||||
container2.register(storyboardType: DipViewController.self, tag: "vc")
|
||||
.resolvingProperties { container, _ in
|
||||
XCTAssertTrue(container === container2)
|
||||
resolved = true
|
||||
}
|
||||
|
||||
DependencyContainer.uiContainers = [container1, container2]
|
||||
storyboard.instantiateViewControllerWithIdentifier("DipViewController")
|
||||
XCTAssertTrue(resolved, "Should resolve using second container")
|
||||
}
|
||||
}
|
||||
|
||||
protocol SomeService: class {
|
||||
var delegate: SomeServiceDelegate? { get set }
|
||||
}
|
||||
protocol SomeServiceDelegate: class { }
|
||||
class SomeServiceImp: SomeService {
|
||||
weak var delegate: SomeServiceDelegate?
|
||||
init(delegate: SomeServiceDelegate) {
|
||||
self.delegate = delegate
|
||||
}
|
||||
init(){}
|
||||
}
|
||||
|
||||
protocol OtherService: class {
|
||||
var delegate: OtherServiceDelegate? { get set }
|
||||
}
|
||||
protocol OtherServiceDelegate: class {}
|
||||
class OtherServiceImp: OtherService {
|
||||
weak var delegate: OtherServiceDelegate?
|
||||
init(delegate: OtherServiceDelegate){
|
||||
self.delegate = delegate
|
||||
}
|
||||
init(){}
|
||||
}
|
||||
|
||||
|
||||
protocol SomeScreen: class {
|
||||
var someService: SomeService? { get set }
|
||||
var otherService: OtherService? { get set }
|
||||
}
|
||||
|
||||
class ViewControllerImp: SomeScreen, SomeServiceDelegate, OtherServiceDelegate {
|
||||
var someService: SomeService?
|
||||
var otherService: OtherService?
|
||||
init(){}
|
||||
}
|
||||
|
||||
extension DipUITests {
|
||||
|
||||
func testThatItDoesNotCreateNewInstanceWhenResolvingDependenciesOfExternalInstance() {
|
||||
let container = DependencyContainer()
|
||||
|
||||
//given
|
||||
var factoryCalled = false
|
||||
container.register(.shared) { () -> SomeScreen in
|
||||
factoryCalled = true
|
||||
return ViewControllerImp() as SomeScreen
|
||||
}
|
||||
|
||||
//when
|
||||
let screen = ViewControllerImp()
|
||||
try! container.resolveDependencies(of: screen as SomeScreen)
|
||||
|
||||
//then
|
||||
XCTAssertFalse(factoryCalled, "Container should not create new instance when resolving dependencies of external instance.")
|
||||
}
|
||||
|
||||
func testThatItResolvesInstanceThatImplementsSeveralProtocols() {
|
||||
let container = DependencyContainer()
|
||||
|
||||
//given
|
||||
container.register(.shared) { ViewControllerImp() as SomeScreen }
|
||||
.resolvingProperties { container, resolved in
|
||||
|
||||
//manually provide resolved instance for the delegate properties
|
||||
resolved.someService = try container.resolve() as SomeService
|
||||
resolved.someService?.delegate = resolved as? SomeServiceDelegate
|
||||
resolved.otherService = try container.resolve(arguments: resolved as! OtherServiceDelegate) as OtherService
|
||||
}
|
||||
|
||||
container.register(.shared) { SomeServiceImp() as SomeService }
|
||||
container.register(.shared) { OtherServiceImp(delegate: $0) as OtherService }
|
||||
|
||||
//when
|
||||
let screen = try! container.resolve() as SomeScreen
|
||||
|
||||
//then
|
||||
XCTAssertNotNil(screen.someService)
|
||||
XCTAssertNotNil(screen.otherService)
|
||||
|
||||
XCTAssertTrue(screen.someService?.delegate === screen)
|
||||
XCTAssertTrue(screen.otherService?.delegate === screen)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -51,22 +51,6 @@ class RuntimeArgumentsTests: XCTestCase {
|
||||
|
||||
let container = DependencyContainer()
|
||||
|
||||
static var allTests = {
|
||||
return [
|
||||
("testThatItResolvesInstanceWithOneArgument", testThatItResolvesInstanceWithOneArgument),
|
||||
("testThatItResolvesInstanceWithTwoArguments", testThatItResolvesInstanceWithTwoArguments),
|
||||
("testThatItResolvesInstanceWithThreeArguments", testThatItResolvesInstanceWithThreeArguments),
|
||||
("testThatItResolvesInstanceWithFourArguments", testThatItResolvesInstanceWithFourArguments),
|
||||
("testThatItResolvesInstanceWithFiveArguments", testThatItResolvesInstanceWithFiveArguments),
|
||||
("testThatItResolvesInstanceWithSixArguments", testThatItResolvesInstanceWithSixArguments),
|
||||
("testThatItRegistersDifferentFactoriesForDifferentNumberOfArguments", testThatItRegistersDifferentFactoriesForDifferentNumberOfArguments),
|
||||
("testThatItRegistersDifferentFactoriesForDifferentTypesOfArguments", testThatItRegistersDifferentFactoriesForDifferentTypesOfArguments),
|
||||
("testThatItRegistersDifferentFactoriesForDifferentOrderOfArguments", testThatItRegistersDifferentFactoriesForDifferentOrderOfArguments),
|
||||
("testThatNewRegistrationWithSameArgumentsOverridesPreviousRegistration", testThatNewRegistrationWithSameArgumentsOverridesPreviousRegistration),
|
||||
("testThatDifferentFactoriesRegisteredIfArgumentIsOptional", testThatDifferentFactoriesRegisteredIfArgumentIsOptional)
|
||||
]
|
||||
}()
|
||||
|
||||
override func setUp() {
|
||||
container.reset()
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
#if canImport(ObjectiveC)
|
||||
import XCTest
|
||||
@testable import Dip
|
||||
|
||||
@@ -48,8 +49,8 @@ private class ServerImp: Server, Hashable {
|
||||
weak var client: Client!
|
||||
init() {}
|
||||
|
||||
var hashValue: Int {
|
||||
return Unmanaged.passUnretained(self).toOpaque().hashValue
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(ObjectIdentifier(self))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,22 +63,6 @@ private var resolvedClients = Array<ClientImp>()
|
||||
|
||||
private var container: DependencyContainer!
|
||||
|
||||
#if os(Linux)
|
||||
import Glibc
|
||||
|
||||
private var runningThreads: Int = 0
|
||||
private var lock: pthread_spinlock_t = 0
|
||||
|
||||
private let resolveClientSync: () -> Client? = {
|
||||
let pointer = dispatch_sync { _ in
|
||||
let resolved = try! container.resolve() as Client
|
||||
return UnsafeMutableRawPointer(Unmanaged.passRetained(resolved as! ClientImp).toOpaque())
|
||||
}
|
||||
guard let clientPointer = pointer else { return nil }
|
||||
return Unmanaged<ClientImp>.fromOpaque(clientPointer).takeRetainedValue()
|
||||
}
|
||||
|
||||
#else
|
||||
let queue = OperationQueue()
|
||||
let lock = RecursiveLock()
|
||||
|
||||
@@ -88,18 +73,11 @@ private let resolveClientSync: () -> Client? = {
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
let resolveServerAsync = {
|
||||
let server = try! container.resolve() as Server
|
||||
lock.lock()
|
||||
resolvedServers.insert(server as! ServerImp)
|
||||
|
||||
#if os(Linux)
|
||||
runningThreads -= 1
|
||||
#endif
|
||||
|
||||
lock.unlock()
|
||||
}
|
||||
|
||||
@@ -107,31 +85,11 @@ let resolveClientAsync = {
|
||||
let client = try! container.resolve() as Client
|
||||
lock.lock()
|
||||
resolvedClients.append(client as! ClientImp)
|
||||
|
||||
#if os(Linux)
|
||||
runningThreads -= 1
|
||||
#endif
|
||||
|
||||
lock.unlock()
|
||||
}
|
||||
|
||||
class ThreadSafetyTests: XCTestCase {
|
||||
|
||||
#if os(Linux)
|
||||
required init(name: String, testClosure: @escaping (XCTestCase) throws -> Void) {
|
||||
pthread_spin_init(&lock, 0)
|
||||
super.init(name: name, testClosure: testClosure)
|
||||
}
|
||||
#endif
|
||||
|
||||
static var allTests = {
|
||||
return [
|
||||
("testSingletonThreadSafety", testSingletonThreadSafety),
|
||||
("testFactoryThreadSafety", testFactoryThreadSafety),
|
||||
("testCircularReferenceThreadSafety", testCircularReferenceThreadSafety)
|
||||
]
|
||||
}()
|
||||
|
||||
override func setUp() {
|
||||
Dip.logLevel = .Verbose
|
||||
container = DependencyContainer()
|
||||
@@ -146,25 +104,10 @@ class ThreadSafetyTests: XCTestCase {
|
||||
container.register(.singleton) { ServerImp() as Server }
|
||||
|
||||
for _ in 0..<100 {
|
||||
#if os(Linux)
|
||||
lock.lock()
|
||||
runningThreads += 1
|
||||
lock.unlock()
|
||||
|
||||
dispatch_async { _ in
|
||||
resolveServerAsync()
|
||||
return nil
|
||||
}
|
||||
#else
|
||||
queue.addOperation(resolveServerAsync)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if os(Linux)
|
||||
while runningThreads > 0 { sleep(1) }
|
||||
#else
|
||||
queue.waitUntilAllOperationsAreFinished()
|
||||
#endif
|
||||
|
||||
XCTAssertEqual(resolvedServers.count, 1, "Should create only one instance")
|
||||
}
|
||||
@@ -174,25 +117,10 @@ class ThreadSafetyTests: XCTestCase {
|
||||
container.register { ServerImp() as Server }
|
||||
|
||||
for _ in 0..<100 {
|
||||
#if os(Linux)
|
||||
lock.lock()
|
||||
runningThreads += 1
|
||||
lock.unlock()
|
||||
|
||||
dispatch_async { _ in
|
||||
resolveServerAsync()
|
||||
return nil
|
||||
}
|
||||
#else
|
||||
queue.addOperation(resolveServerAsync)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if os(Linux)
|
||||
while runningThreads > 0 { sleep(1) }
|
||||
#else
|
||||
queue.waitUntilAllOperationsAreFinished()
|
||||
#endif
|
||||
|
||||
XCTAssertEqual(resolvedServers.count, 100, "All instances should be different")
|
||||
}
|
||||
@@ -209,25 +137,10 @@ class ThreadSafetyTests: XCTestCase {
|
||||
}
|
||||
|
||||
for _ in 0..<100 {
|
||||
#if os(Linux)
|
||||
lock.lock()
|
||||
runningThreads += 1
|
||||
lock.unlock()
|
||||
|
||||
dispatch_async { _ in
|
||||
resolveClientAsync()
|
||||
return nil
|
||||
}
|
||||
#else
|
||||
queue.addOperation(resolveClientAsync)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if os(Linux)
|
||||
while runningThreads > 0 { sleep(1) }
|
||||
#else
|
||||
queue.waitUntilAllOperationsAreFinished()
|
||||
#endif
|
||||
|
||||
XCTAssertEqual(resolvedClients.count, 100, "Instances should be not reused in different object graphs")
|
||||
for client in resolvedClients {
|
||||
@@ -238,5 +151,4 @@ class ThreadSafetyTests: XCTestCase {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,29 +27,36 @@ import XCTest
|
||||
|
||||
private protocol Service: class { }
|
||||
private protocol ForwardedType: class { }
|
||||
#if os(Linux)
|
||||
private class ServiceImp1: Service, ForwardedType { }
|
||||
private class ServiceImp2: Service, ForwardedType { }
|
||||
#else
|
||||
private class ServiceImp1: NSObject, Service, ForwardedType { }
|
||||
private class ServiceImp2: NSObject, Service, ForwardedType { }
|
||||
#endif
|
||||
|
||||
private protocol Dependency {}
|
||||
private struct DependencyImpl: Dependency {}
|
||||
private class DependencyRefImpl: Dependency {}
|
||||
|
||||
private struct DependencyClient {
|
||||
let dep: Dependency
|
||||
init(dependency: Dependency) {
|
||||
self.dep = dependency
|
||||
}
|
||||
}
|
||||
|
||||
private struct OptionalDependencyClient {
|
||||
let dep: Dependency?
|
||||
init(dependency: Dependency?) {
|
||||
self.dep = dependency
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TypeForwardingTests: XCTestCase {
|
||||
|
||||
let container = DependencyContainer()
|
||||
|
||||
static var allTests = {
|
||||
return [
|
||||
("testThatItResolvesInstanceByTypeForwarding", testThatItResolvesInstanceByTypeForwarding),
|
||||
("testThatItReusesInstanceResolvedByTypeForwarding", testThatItReusesInstanceResolvedByTypeForwarding),
|
||||
("testThatItDoesNotResolveByTypeForwardingIfRegisteredForAnotherTag", testThatItDoesNotResolveByTypeForwardingIfRegisteredForAnotherTag),
|
||||
("testThatItDoesNotReuseInstanceResolvedByTypeForwardingRegisteredForAnotherTag", testThatItDoesNotReuseInstanceResolvedByTypeForwardingRegisteredForAnotherTag),
|
||||
("testThatItCallsResolvedDependenciesBlockWhenResolvingByTypeForwarding", testThatItCallsResolvedDependenciesBlockWhenResolvingByTypeForwarding),
|
||||
("testThatItCallsResolvedDependenciesBlockProvidedAfterRegistrationWhenResolvingByTypeForwarding",testThatItCallsResolvedDependenciesBlockProvidedAfterRegistrationWhenResolvingByTypeForwarding),
|
||||
("testThatItFallbackToDefinitionWithNoTagWhenResolvingInstanceByTypeForwarding", testThatItFallbackToDefinitionWithNoTagWhenResolvingInstanceByTypeForwarding),
|
||||
("testThatItCanResolveOptional", testThatItCanResolveOptional),
|
||||
("testThatItFirstUsesTaggedDefinitionWhenResolvingOptional", testThatItFirstUsesTaggedDefinitionWhenResolvingOptional),
|
||||
("testThatItThrowsErrorWhenResolvingNotImplementedTypeWithTypeForwarding", testThatItThrowsErrorWhenResolvingNotImplementedTypeWithTypeForwarding),
|
||||
("testThatItOverridesIfSeveralDefinitionsWithTheSameTagForwardTheSameType", testThatItOverridesIfSeveralDefinitionsWithTheSameTagForwardTheSameType),
|
||||
("testThatItDoesNotOverrideIfDefinitionForwardsTheSameTypeWithDifferentTag", testThatItDoesNotOverrideIfDefinitionForwardsTheSameTypeWithDifferentTag)
|
||||
]
|
||||
}()
|
||||
|
||||
override func setUp() {
|
||||
container.reset()
|
||||
@@ -109,15 +116,15 @@ class TypeForwardingTests: XCTestCase {
|
||||
def.implements(ForwardedType.self, tag: "otherTag")
|
||||
|
||||
//then
|
||||
AssertThrows(expression: try container.resolve(tag: "tag") as ForwardedType)
|
||||
AssertThrows(expression: try container.resolve(ForwardedType.self, tag: "tag"))
|
||||
XCTAssertThrowsError(try self.container.resolve(tag: "tag") as ForwardedType)
|
||||
XCTAssertThrowsError(try self.container.resolve(ForwardedType.self, tag: "tag"))
|
||||
|
||||
//and given
|
||||
def.implements(ForwardedType.self, tag: "tag")
|
||||
|
||||
//then
|
||||
AssertNoThrow(expression: try container.resolve(tag: "tag") as ForwardedType)
|
||||
AssertNoThrow(expression: try container.resolve(ForwardedType.self, tag: "tag"))
|
||||
XCTAssertNoThrow(try self.container.resolve(tag: "tag") as ForwardedType)
|
||||
XCTAssertNoThrow(try self.container.resolve(ForwardedType.self, tag: "tag"))
|
||||
}
|
||||
|
||||
func testThatItDoesNotReuseInstanceResolvedByTypeForwardingRegisteredForAnotherTag() {
|
||||
@@ -252,6 +259,35 @@ class TypeForwardingTests: XCTestCase {
|
||||
XCTAssertTrue(object is ServiceImp1)
|
||||
XCTAssertTrue(anyObject is ServiceImp1)
|
||||
}
|
||||
|
||||
func testThatItReusesInstancesResolvedForOptionalType() {
|
||||
var alreadyResolved = false
|
||||
container.register(.singleton) { () -> Dependency in
|
||||
XCTAssertFalse(alreadyResolved)
|
||||
return DependencyImpl() as Dependency
|
||||
}
|
||||
container.register() { DependencyClient(dependency: try! self.container.resolve()) }
|
||||
container.register() { OptionalDependencyClient(dependency: try! self.container.resolve()) }
|
||||
|
||||
let _ = try! container.resolve() as OptionalDependencyClient
|
||||
let _ = try! container.resolve() as DependencyClient
|
||||
|
||||
alreadyResolved = false
|
||||
|
||||
let _ = try! container.resolve() as DependencyClient
|
||||
let _ = try! container.resolve() as OptionalDependencyClient
|
||||
|
||||
container.register(.singleton) { () -> Dependency in
|
||||
XCTAssertFalse(alreadyResolved)
|
||||
return DependencyRefImpl() as Dependency
|
||||
}
|
||||
|
||||
let client1 = try! container.resolve() as DependencyClient
|
||||
let client2 = try! container.resolve() as OptionalDependencyClient
|
||||
|
||||
XCTAssertTrue(client1.dep as! DependencyRefImpl === client2.dep as! DependencyRefImpl)
|
||||
}
|
||||
|
||||
|
||||
func testThatItFirstUsesTaggedDefinitionWhenResolvingOptional() {
|
||||
let expectedTag: DependencyContainer.Tag = .String("tag")
|
||||
@@ -276,19 +312,23 @@ class TypeForwardingTests: XCTestCase {
|
||||
.implements(ServiceImp2.self)
|
||||
|
||||
//then
|
||||
AssertThrows(expression: try container.resolve() as ServiceImp2) { error in
|
||||
guard case let DipError.invalidType(_, key) = error else { return false }
|
||||
XCTAssertThrowsError(try self.container.resolve() as ServiceImp2) { error in
|
||||
guard case let DipError.invalidType(_, key) = error else {
|
||||
XCTFail("Thrown unexpected error: \(error)")
|
||||
return
|
||||
}
|
||||
|
||||
let expectedKey = DefinitionKey(type: ServiceImp2.self, typeOfArguments: Void.self, tag: nil)
|
||||
XCTAssertEqual(key, expectedKey)
|
||||
return true
|
||||
}
|
||||
AssertThrows(expression: try container.resolve(ServiceImp2.self)) { error in
|
||||
guard case let DipError.invalidType(_, key) = error else { return false }
|
||||
XCTAssertThrowsError(try self.container.resolve(ServiceImp2.self)) { error in
|
||||
guard case let DipError.invalidType(_, key) = error else {
|
||||
XCTFail("Thrown unexpected error: \(error)")
|
||||
return
|
||||
}
|
||||
|
||||
let expectedKey = DefinitionKey(type: ServiceImp2.self, typeOfArguments: Void.self, tag: nil)
|
||||
XCTAssertEqual(key, expectedKey)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,41 +28,6 @@ import XCTest
|
||||
typealias NSObject = AnyObject
|
||||
#endif
|
||||
|
||||
func AssertThrows<T>(_ file: StaticString = #file, line: UInt = #line, expression: @autoclosure () throws -> T) {
|
||||
AssertThrows(file, line: line, expression: expression, "")
|
||||
}
|
||||
|
||||
func AssertThrows<T>(_ file: StaticString = #file, line: UInt = #line, expression: @autoclosure () throws -> T, _ message: String) {
|
||||
AssertThrows(expression: expression, checkError: { _ in true }, message)
|
||||
}
|
||||
|
||||
func AssertThrows<T>(_ file: StaticString = #file, line: UInt = #line, expression: @autoclosure () throws -> T, checkError: (Error) -> Bool) {
|
||||
AssertThrows(file, line: line, expression: expression, checkError: checkError, "")
|
||||
}
|
||||
|
||||
func AssertThrows<T>(_ file: StaticString = #file, line: UInt = #line, expression: @autoclosure () throws -> T, checkError: (Error) -> Bool, _ message: String) {
|
||||
do {
|
||||
let _ = try expression()
|
||||
XCTFail(message, file: file, line: line)
|
||||
}
|
||||
catch {
|
||||
XCTAssertTrue(checkError(error), "Thrown unexpected error: \(error)", file: file, line: line)
|
||||
}
|
||||
}
|
||||
|
||||
func AssertNoThrow<T>(_ file: StaticString = #file, line: UInt = #line, expression: @autoclosure () throws -> T) {
|
||||
AssertNoThrow(file, line: line, expression: expression, "")
|
||||
}
|
||||
|
||||
func AssertNoThrow<T>(_ file: StaticString = #file, line: UInt = #line, expression: @autoclosure () throws -> T, _ message: String) {
|
||||
do {
|
||||
let _ = try expression()
|
||||
}
|
||||
catch {
|
||||
XCTFail(message, file: file, line: line)
|
||||
}
|
||||
}
|
||||
|
||||
#if os(Linux)
|
||||
import Glibc
|
||||
typealias TMain = @convention(c) (UnsafeMutableRawPointer?) -> UnsafeMutableRawPointer?
|
||||
@@ -78,7 +43,7 @@ func dispatch_async(block: @escaping TMain) -> pthread_t {
|
||||
}
|
||||
|
||||
func dispatch_sync(block: @escaping TMain) -> UnsafeMutableRawPointer? {
|
||||
var result: UnsafeMutableRawPointer? = UnsafeMutableRawPointer.allocate(bytes: 1, alignedTo: 0)
|
||||
var result: UnsafeMutableRawPointer? = UnsafeMutableRawPointer.allocate(byteCount: 1, alignment: 0)
|
||||
let pid = startThread(block)
|
||||
pthread_join(pid, &result)
|
||||
return result
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import XCTest
|
||||
@testable import DipTests
|
||||
|
||||
XCTMain([
|
||||
testCase(DipTests.allTests),
|
||||
testCase(DefinitionTests.allTests),
|
||||
testCase(RuntimeArgumentsTests.allTests),
|
||||
testCase(ComponentScopeTests.allTests),
|
||||
testCase(AutoInjectionTests.allTests),
|
||||
// testCase(ThreadSafetyTests.allTests),
|
||||
testCase(AutoWiringTests.allTests),
|
||||
testCase(ContextTests.allTests),
|
||||
testCase(TypeForwardingTests.allTests)
|
||||
])
|
||||
@@ -0,0 +1,202 @@
|
||||
#if !canImport(ObjectiveC)
|
||||
import XCTest
|
||||
|
||||
extension AutoInjectionTests {
|
||||
// DO NOT MODIFY: This is autogenerated, use:
|
||||
// `swift test --generate-linuxmain`
|
||||
// to regenerate.
|
||||
static let __allTests__AutoInjectionTests = [
|
||||
("testThatItAutoInjectsPropertyWithCollaboratingContainer", testThatItAutoInjectsPropertyWithCollaboratingContainer),
|
||||
("testThatItAutoInjectsWhenOverridenInDefinition", testThatItAutoInjectsWhenOverridenInDefinition),
|
||||
("testThatItCallsDidInjectOnAutoInjectedProperty", testThatItCallsDidInjectOnAutoInjectedProperty),
|
||||
("testThatItCallsResolveDependencyBlockWhenAutoInjecting", testThatItCallsResolveDependencyBlockWhenAutoInjecting),
|
||||
("testThatItDoesNotAutoInjectIfDisabledInContainer", testThatItDoesNotAutoInjectIfDisabledInContainer),
|
||||
("testThatItDoesNotAutoInjectIfDisabledInDefinition", testThatItDoesNotAutoInjectIfDisabledInDefinition),
|
||||
("testThatItDoesNotPassTagToAutoInjectedPropertyWithExplicitTag", testThatItDoesNotPassTagToAutoInjectedPropertyWithExplicitTag),
|
||||
("testThatItPassesTagToAutoInjectedProperty", testThatItPassesTagToAutoInjectedProperty),
|
||||
("testThatItResolvesAutoInjectedDependencies", testThatItResolvesAutoInjectedDependencies),
|
||||
("testThatItResolvesAutoInjectedSingletons", testThatItResolvesAutoInjectedSingletons),
|
||||
("testThatItResolvesInheritedDependencies", testThatItResolvesInheritedDependencies),
|
||||
("testThatItResolvesTaggedAutoInjectedProperties", testThatItResolvesTaggedAutoInjectedProperties),
|
||||
("testThatItReusesAutoInjectedInstancesOnNextResolveOrAutoInjection", testThatItReusesAutoInjectedInstancesOnNextResolveOrAutoInjection),
|
||||
("testThatItReusesResolvedAutoInjectedInstances", testThatItReusesResolvedAutoInjectedInstances),
|
||||
("testThatItThrowsErrorIfFailsToAutoInjectDependency", testThatItThrowsErrorIfFailsToAutoInjectDependency),
|
||||
("testThatNoErrorThrownWhenOptionalPropertiesAreNotAutoInjected", testThatNoErrorThrownWhenOptionalPropertiesAreNotAutoInjected),
|
||||
("testThatThereIsNoRetainCycleBetweenAutoInjectedCircularDependencies", testThatThereIsNoRetainCycleBetweenAutoInjectedCircularDependencies),
|
||||
]
|
||||
}
|
||||
|
||||
extension AutoWiringTests {
|
||||
// DO NOT MODIFY: This is autogenerated, use:
|
||||
// `swift test --generate-linuxmain`
|
||||
// to regenerate.
|
||||
static let __allTests__AutoWiringTests = [
|
||||
("testThatItCanAutoWireOptional", testThatItCanAutoWireOptional),
|
||||
("testThatItCanResolveWithAutoWiring", testThatItCanResolveWithAutoWiring),
|
||||
("testThatItDoesNotReuseInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgainWithAnotherTag", testThatItDoesNotReuseInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgainWithAnotherTag),
|
||||
("testThatItDoesNotTryToUseAutoWiringWhenCallingResolveWithArguments", testThatItDoesNotTryToUseAutoWiringWhenCallingResolveWithArguments),
|
||||
("testThatItDoesNotUseAutoWiringWhenFailedToResolveLowLevelDependency", testThatItDoesNotUseAutoWiringWhenFailedToResolveLowLevelDependency),
|
||||
("testThatItFallbackToNotTaggedFactoryWhenUsingAutoWire", testThatItFallbackToNotTaggedFactoryWhenUsingAutoWire),
|
||||
("testThatItPrefersTaggedFactoryWithDifferentNumberOfArgumentsWhenUsingAutoWire", testThatItPrefersTaggedFactoryWithDifferentNumberOfArgumentsWhenUsingAutoWire),
|
||||
("testThatItPrefersTaggedFactoryWithDifferentTypesOfArgumentsWhenUsingAutoWire", testThatItPrefersTaggedFactoryWithDifferentTypesOfArgumentsWhenUsingAutoWire),
|
||||
("testThatItReusesInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgain", testThatItReusesInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgain),
|
||||
("testThatItReusesInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgainWithTheSameTag", testThatItReusesInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgainWithTheSameTag),
|
||||
("testThatItReusesInstancesResolvedWithoutAutoWiringWhenUsingAutoWiringAgain", testThatItReusesInstancesResolvedWithoutAutoWiringWhenUsingAutoWiringAgain),
|
||||
("testThatItThrowsAmbiguityErrorWhenUsingAutoWire", testThatItThrowsAmbiguityErrorWhenUsingAutoWire),
|
||||
("testThatItUsesAutoWireFactoryWithMostNumberOfArguments", testThatItUsesAutoWireFactoryWithMostNumberOfArguments),
|
||||
("testThatItUsesTagToResolveDependenciesWithAutoWiringWith1Argument", testThatItUsesTagToResolveDependenciesWithAutoWiringWith1Argument),
|
||||
("testThatItUsesTagToResolveDependenciesWithAutoWiringWith2Arguments", testThatItUsesTagToResolveDependenciesWithAutoWiringWith2Arguments),
|
||||
("testThatItUsesTagToResolveDependenciesWithAutoWiringWith3Arguments", testThatItUsesTagToResolveDependenciesWithAutoWiringWith3Arguments),
|
||||
("testThatItUsesTagToResolveDependenciesWithAutoWiringWith4Arguments", testThatItUsesTagToResolveDependenciesWithAutoWiringWith4Arguments),
|
||||
("testThatItUsesTagToResolveDependenciesWithAutoWiringWith5Arguments", testThatItUsesTagToResolveDependenciesWithAutoWiringWith5Arguments),
|
||||
("testThatItUsesTagToResolveDependenciesWithAutoWiringWith6Arguments", testThatItUsesTagToResolveDependenciesWithAutoWiringWith6Arguments),
|
||||
]
|
||||
}
|
||||
|
||||
extension ComponentScopeTests {
|
||||
// DO NOT MODIFY: This is autogenerated, use:
|
||||
// `swift test --generate-linuxmain`
|
||||
// to regenerate.
|
||||
static let __allTests__ComponentScopeTests = [
|
||||
("testThatCollaboratingContainersReuseSingletonsResolvedByAnotherContainer", testThatCollaboratingContainersReuseSingletonsResolvedByAnotherContainer),
|
||||
("testThatContainerCanBeBootstrappedAgainAfterReset", testThatContainerCanBeBootstrappedAgainAfterReset),
|
||||
("testThatItDoesNotReuseInstanceInSharedScopeInNextResolve", testThatItDoesNotReuseInstanceInSharedScopeInNextResolve),
|
||||
("testThatItDoesNotReuseInstanceInSharedScopeResolvedForNilTagWhenResolvingForAnotherTag", testThatItDoesNotReuseInstanceInSharedScopeResolvedForNilTagWhenResolvingForAnotherTag),
|
||||
("testThatItHoldsWeakReferenceToWeakSingletonInstance", testThatItHoldsWeakReferenceToWeakSingletonInstance),
|
||||
("testThatItResolvesTypeAsNewInstanceForUniqueScope", testThatItResolvesTypeAsNewInstanceForUniqueScope),
|
||||
("testThatItResolvesWeakSingletonAgainAfterItWasReleased", testThatItResolvesWeakSingletonAgainAfterItWasReleased),
|
||||
("testThatItReusesInstanceForSingletonScope", testThatItReusesInstanceForSingletonScope),
|
||||
("testThatItReusesInstanceInSharedScopeDuringResolve", testThatItReusesInstanceInSharedScopeDuringResolve),
|
||||
("testThatItReusesInstanceInSharedScopeResolvedForNilTag", testThatItReusesInstanceInSharedScopeResolvedForNilTag),
|
||||
("testThatItReusesResolvedInstanceWhenResolvingOptional", testThatItReusesResolvedInstanceWhenResolvingOptional),
|
||||
("testThatOnlyEagerSingletonIsCreatedWhenContainerIsBootsrapped", testThatOnlyEagerSingletonIsCreatedWhenContainerIsBootsrapped),
|
||||
("testThatScopeCanBeChanged", testThatScopeCanBeChanged),
|
||||
("testThatSharedIsDefaultScope", testThatSharedIsDefaultScope),
|
||||
("testThatSingletonIsNotReusedAcrossContainers", testThatSingletonIsNotReusedAcrossContainers),
|
||||
("testThatSingletonIsReleasedWhenContainerIsReset", testThatSingletonIsReleasedWhenContainerIsReset),
|
||||
("testThatSingletonIsReleasedWhenDefinitionIsOverridden", testThatSingletonIsReleasedWhenDefinitionIsOverridden),
|
||||
("testThatSingletonIsReleasedWhenDefinitionIsRemoved", testThatSingletonIsReleasedWhenDefinitionIsRemoved),
|
||||
]
|
||||
}
|
||||
|
||||
extension ContextTests {
|
||||
// DO NOT MODIFY: This is autogenerated, use:
|
||||
// `swift test --generate-linuxmain`
|
||||
// to regenerate.
|
||||
static let __allTests__ContextTests = [
|
||||
("testThatContextDoesNotOverrideNilTagPassedToResolve", testThatContextDoesNotOverrideNilTagPassedToResolve),
|
||||
("testThatContextIsPreservedWhenResolvingWithCollaboration", testThatContextIsPreservedWhenResolvingWithCollaboration),
|
||||
("testThatContextStoresCurrentlyResolvedType", testThatContextStoresCurrentlyResolvedType),
|
||||
("testThatContextStoresInjectedInType", testThatContextStoresInjectedInType),
|
||||
("testThatContextStoresNameOfAutoInjectedProperty", testThatContextStoresNameOfAutoInjectedProperty),
|
||||
("testThatContextStoresTheTagPassedToResolve", testThatContextStoresTheTagPassedToResolve),
|
||||
("testThatContextStoresTheTagPassedToResolveWhenAutoInjecting", testThatContextStoresTheTagPassedToResolveWhenAutoInjecting),
|
||||
("testThatContextStoresTheTagPassedToResolveWhenAutoWiring", testThatContextStoresTheTagPassedToResolveWhenAutoWiring),
|
||||
("testThatItDoesNotSetInjectedInTypeWhenResolvingWithCollaboration", testThatItDoesNotSetInjectedInTypeWhenResolvingWithCollaboration),
|
||||
]
|
||||
}
|
||||
|
||||
extension DefinitionTests {
|
||||
// DO NOT MODIFY: This is autogenerated, use:
|
||||
// `swift test --generate-linuxmain`
|
||||
// to regenerate.
|
||||
static let __allTests__DefinitionTests = [
|
||||
("testThatDefinitionKeyIsEqualBy_Type_Factory_Tag", testThatDefinitionKeyIsEqualBy_Type_Factory_Tag),
|
||||
("testThatDefinitionKeysWithDifferentFactoriesAreNotEqual", testThatDefinitionKeysWithDifferentFactoriesAreNotEqual),
|
||||
("testThatDefinitionKeysWithDifferentTagsAreNotEqual", testThatDefinitionKeysWithDifferentTagsAreNotEqual),
|
||||
("testThatDefinitionKeysWithDifferentTypesAreNotEqual", testThatDefinitionKeysWithDifferentTypesAreNotEqual),
|
||||
("testThatItRegisteresOptionalTypesAsForwardedTypes", testThatItRegisteresOptionalTypesAsForwardedTypes),
|
||||
("testThatResolveDependenciesBlockIsNotCalledWhenPassedWrongInstance", testThatResolveDependenciesBlockIsNotCalledWhenPassedWrongInstance),
|
||||
("testThatResolveDependenciesCallsResolveDependenciesBlock", testThatResolveDependenciesCallsResolveDependenciesBlock),
|
||||
]
|
||||
}
|
||||
|
||||
extension DipTests {
|
||||
// DO NOT MODIFY: This is autogenerated, use:
|
||||
// `swift test --generate-linuxmain`
|
||||
// to regenerate.
|
||||
static let __allTests__DipTests = [
|
||||
("test_weak_mirror_regression", test_weak_mirror_regression),
|
||||
("testItCallsResolveDependenciesOnResolableInstance", testItCallsResolveDependenciesOnResolableInstance),
|
||||
("testThatCollaboratingContainersAreWeakReferences", testThatCollaboratingContainersAreWeakReferences),
|
||||
("testThatCollaboratingContainersReuseInstancesResolvedByAnotherContainer", testThatCollaboratingContainersReuseInstancesResolvedByAnotherContainer),
|
||||
("testThatCollaboratingWithSelfIsIgnored", testThatCollaboratingWithSelfIsIgnored),
|
||||
("testThatCollaborationReferencesAreRecursivelyUpdate", testThatCollaborationReferencesAreRecursivelyUpdate),
|
||||
("testThatContainerAutowireBeforeCollaboration", testThatContainerAutowireBeforeCollaboration),
|
||||
("testThatContainersShareTheirSingletonsOnlyWithCollaborators", testThatContainersShareTheirSingletonsOnlyWithCollaborators),
|
||||
("testThatCreatingContainerWithConfigBlockDoesNotCreateRetainCycle", testThatCreatingContainerWithConfigBlockDoesNotCreateRetainCycle),
|
||||
("testThatItCallsDidResolveDependenciesInReverseOrder", testThatItCallsDidResolveDependenciesInReverseOrder),
|
||||
("testThatItCallsDidResolveDependenciesOnResolvableIntance", testThatItCallsDidResolveDependenciesOnResolvableIntance),
|
||||
("testThatItCallsResolveDependenciesOnDefinition", testThatItCallsResolveDependenciesOnDefinition),
|
||||
("testThatItCanHandleSeparateContainersAndTheirCollaboration", testThatItCanHandleSeparateContainersAndTheirCollaboration),
|
||||
("testThatItCanResolveUsingContainersCollaboration", testThatItCanResolveUsingContainersCollaboration),
|
||||
("testThatItFailsValidationIfNoMatchingArgumentsFound", testThatItFailsValidationIfNoMatchingArgumentsFound),
|
||||
("testThatItFailsValidationOnlyForDipErrors", testThatItFailsValidationOnlyForDipErrors),
|
||||
("testThatItPicksRuntimeArgumentsWhenValidatingConfiguration", testThatItPicksRuntimeArgumentsWhenValidatingConfiguration),
|
||||
("testThatItResolvesCircularDependencies", testThatItResolvesCircularDependencies),
|
||||
("testThatItResolvesDifferentInstancesRegisteredForDifferentTags", testThatItResolvesDifferentInstancesRegisteredForDifferentTags),
|
||||
("testThatItResolvesInstanceRegisteredWithoutTag", testThatItResolvesInstanceRegisteredWithoutTag),
|
||||
("testThatItResolvesInstanceRegisteredWithTag", testThatItResolvesInstanceRegisteredWithTag),
|
||||
("testThatItThrowsErrorIfCanNotFindDefinitionForFactoryWithArguments", testThatItThrowsErrorIfCanNotFindDefinitionForFactoryWithArguments),
|
||||
("testThatItThrowsErrorIfCanNotFindDefinitionForTag", testThatItThrowsErrorIfCanNotFindDefinitionForTag),
|
||||
("testThatItThrowsErrorIfCanNotFindDefinitionForType", testThatItThrowsErrorIfCanNotFindDefinitionForType),
|
||||
("testThatItThrowsErrorIfConstructorThrows", testThatItThrowsErrorIfConstructorThrows),
|
||||
("testThatItThrowsErrorIfFailsToResolveDependency", testThatItThrowsErrorIfFailsToResolveDependency),
|
||||
("testThatItValidatesConfiguration", testThatItValidatesConfiguration),
|
||||
("testThatNewRegistrationOverridesPreviousRegistration", testThatNewRegistrationOverridesPreviousRegistration),
|
||||
]
|
||||
}
|
||||
|
||||
extension RuntimeArgumentsTests {
|
||||
// DO NOT MODIFY: This is autogenerated, use:
|
||||
// `swift test --generate-linuxmain`
|
||||
// to regenerate.
|
||||
static let __allTests__RuntimeArgumentsTests = [
|
||||
("testThatDifferentFactoriesRegisteredIfArgumentIsOptional", testThatDifferentFactoriesRegisteredIfArgumentIsOptional),
|
||||
("testThatItRegistersDifferentFactoriesForDifferentNumberOfArguments", testThatItRegistersDifferentFactoriesForDifferentNumberOfArguments),
|
||||
("testThatItRegistersDifferentFactoriesForDifferentOrderOfArguments", testThatItRegistersDifferentFactoriesForDifferentOrderOfArguments),
|
||||
("testThatItRegistersDifferentFactoriesForDifferentTypesOfArguments", testThatItRegistersDifferentFactoriesForDifferentTypesOfArguments),
|
||||
("testThatItResolvesInstanceWithFiveArguments", testThatItResolvesInstanceWithFiveArguments),
|
||||
("testThatItResolvesInstanceWithFourArguments", testThatItResolvesInstanceWithFourArguments),
|
||||
("testThatItResolvesInstanceWithOneArgument", testThatItResolvesInstanceWithOneArgument),
|
||||
("testThatItResolvesInstanceWithSixArguments", testThatItResolvesInstanceWithSixArguments),
|
||||
("testThatItResolvesInstanceWithThreeArguments", testThatItResolvesInstanceWithThreeArguments),
|
||||
("testThatItResolvesInstanceWithTwoArguments", testThatItResolvesInstanceWithTwoArguments),
|
||||
("testThatNewRegistrationWithSameArgumentsOverridesPreviousRegistration", testThatNewRegistrationWithSameArgumentsOverridesPreviousRegistration),
|
||||
]
|
||||
}
|
||||
|
||||
extension TypeForwardingTests {
|
||||
// DO NOT MODIFY: This is autogenerated, use:
|
||||
// `swift test --generate-linuxmain`
|
||||
// to regenerate.
|
||||
static let __allTests__TypeForwardingTests = [
|
||||
("testThatItCallsResolvedDependenciesBlockProvidedAfterRegistrationWhenResolvingByTypeForwarding", testThatItCallsResolvedDependenciesBlockProvidedAfterRegistrationWhenResolvingByTypeForwarding),
|
||||
("testThatItCallsResolvedDependenciesBlockWhenResolvingByTypeForwarding", testThatItCallsResolvedDependenciesBlockWhenResolvingByTypeForwarding),
|
||||
("testThatItCanResolveOptional", testThatItCanResolveOptional),
|
||||
("testThatItDoesNotOverrideIfDefinitionForwardsTheSameTypeWithDifferentTag", testThatItDoesNotOverrideIfDefinitionForwardsTheSameTypeWithDifferentTag),
|
||||
("testThatItDoesNotResolveByTypeForwardingIfRegisteredForAnotherTag", testThatItDoesNotResolveByTypeForwardingIfRegisteredForAnotherTag),
|
||||
("testThatItDoesNotReuseInstanceResolvedByTypeForwardingRegisteredForAnotherTag", testThatItDoesNotReuseInstanceResolvedByTypeForwardingRegisteredForAnotherTag),
|
||||
("testThatItFallbackToDefinitionWithNoTagWhenResolvingInstanceByTypeForwarding", testThatItFallbackToDefinitionWithNoTagWhenResolvingInstanceByTypeForwarding),
|
||||
("testThatItFirstUsesTaggedDefinitionWhenResolvingOptional", testThatItFirstUsesTaggedDefinitionWhenResolvingOptional),
|
||||
("testThatItOverridesIfSeveralDefinitionsWithTheSameTagForwardTheSameType", testThatItOverridesIfSeveralDefinitionsWithTheSameTagForwardTheSameType),
|
||||
("testThatItResolvesInstanceByTypeForwarding", testThatItResolvesInstanceByTypeForwarding),
|
||||
("testThatItReusesInstanceResolvedByTypeForwarding", testThatItReusesInstanceResolvedByTypeForwarding),
|
||||
("testThatItReusesInstancesResolvedForOptionalType", testThatItReusesInstancesResolvedForOptionalType),
|
||||
("testThatItThrowsErrorWhenResolvingNotImplementedTypeWithTypeForwarding", testThatItThrowsErrorWhenResolvingNotImplementedTypeWithTypeForwarding),
|
||||
]
|
||||
}
|
||||
|
||||
public func __allTests() -> [XCTestCaseEntry] {
|
||||
return [
|
||||
testCase(AutoInjectionTests.__allTests__AutoInjectionTests),
|
||||
testCase(AutoWiringTests.__allTests__AutoWiringTests),
|
||||
testCase(ComponentScopeTests.__allTests__ComponentScopeTests),
|
||||
testCase(ContextTests.__allTests__ContextTests),
|
||||
testCase(DefinitionTests.__allTests__DefinitionTests),
|
||||
testCase(DipTests.__allTests__DipTests),
|
||||
testCase(RuntimeArgumentsTests.__allTests__RuntimeArgumentsTests),
|
||||
testCase(TypeForwardingTests.__allTests__TypeForwardingTests),
|
||||
]
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user