├── README.md ├── CODEOWNERS ├── CBInjection ├── Models │ ├── InjectionParameterName.swift │ ├── InjectionScope.swift │ ├── DependencyInjection.swift │ ├── ViewControllerInjectionKey.swift │ └── InjectionKey.swift ├── Module │ ├── CBInjection.h │ └── Info.plist ├── Errors │ └── DependenciesError.swift ├── Extensions │ ├── UIViewController+Injectables.swift │ └── UINavigationController+Injectables.swift └── Dependency │ └── Dependencies.swift ├── CBInjection.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── xcshareddata │ └── xcschemes │ │ └── CBInjection.xcscheme └── project.pbxproj ├── LICENSE ├── .gitignore ├── CBInjection.podspec └── CBInjectionTests ├── Info.plist └── DependenciesTests.swift /README.md: -------------------------------------------------------------------------------- 1 | # CBInjection 2 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @hishbase @petejkim @andrewgold @johnnycoinbase 2 | 3 | -------------------------------------------------------------------------------- /CBInjection/Models/InjectionParameterName.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Coinbase Inc. See LICENSE 2 | 3 | import Foundation 4 | 5 | /// Represents an injection parameter name. Used to pass parameters from InjectionKey 6 | public typealias InjectionParameterName = String 7 | -------------------------------------------------------------------------------- /CBInjection.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CBInjection/Module/CBInjection.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | //! Project version number for CBInjection. 5 | FOUNDATION_EXPORT double CBInjectionVersionNumber; 6 | 7 | //! Project version string for CBInjection. 8 | FOUNDATION_EXPORT const unsigned char CBInjectionVersionString[]; 9 | 10 | -------------------------------------------------------------------------------- /CBInjection.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /CBInjection/Models/InjectionScope.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Coinbase Inc. See LICENSE 2 | 3 | import Foundation 4 | 5 | /// Represents the support object scope 6 | public enum InjectionScope { 7 | /// This means a new instance is created every time the dependency is resolved 8 | case transient 9 | 10 | /// This returns a single instance every time the dependency is resolved 11 | case singleton 12 | } 13 | -------------------------------------------------------------------------------- /CBInjection/Errors/DependenciesError.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Coinbase Inc. See LICENSE 2 | 3 | import Foundation 4 | 5 | /// Dependencies-related Error 6 | public enum DependenciesError: Error { 7 | /// Error thrown when unable to resolve dependency 8 | case unableToResolveDependency(InjectionKeys) 9 | 10 | /// Error thrown when injection doesn't supply the correct list of parameters 11 | case missingParameters 12 | 13 | /// Error thrown when injection is not implemented while resolving a key 14 | case injectionNotImplemented 15 | } 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Coinbase, Inc. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /CBInjection/Models/DependencyInjection.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Coinbase Inc. See LICENSE 2 | 3 | /// Conformers of this protocol can resolve a dependency 4 | open class DependencyInjection { 5 | /// Default constructor 6 | public required init() {} 7 | 8 | /// Resolve dependency 9 | /// 10 | /// - Parameters: 11 | /// - dependencies: provider for resolving other dependencies 12 | /// 13 | /// - Returns: Instance of the requested dependency or an error is thrown 14 | open func provide(using _: Dependencies, parameters _: [InjectionParameterName: Any]) throws -> T { 15 | throw DependenciesError.injectionNotImplemented 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | .AppleDouble 4 | .LSOverride 5 | Icon 6 | ._* 7 | .Spotlight-V100 8 | .Trashes 9 | 10 | # Xcode 11 | *.pbxuser 12 | !default.pbxuser 13 | *.mode1v3 14 | !default.mode1v3 15 | *.mode2v3 16 | !default.mode2v3 17 | *.perspectivev3 18 | !default.perspectivev3 19 | xcuserdata 20 | *.xccheckout 21 | *.moved-aside 22 | DerivedData 23 | *.hmap 24 | *.ipa 25 | *.xcuserstate 26 | *.xcscmblueprint 27 | *.gcno 28 | *.gcda 29 | 30 | # Carthage 31 | /Carthage/Checkouts 32 | Carthage/Build/Mac 33 | Carthage/Build/tvOS 34 | Carthage/Build/watchOS 35 | Carthage/Build/.*.version 36 | 37 | # AppCode 38 | /.idea 39 | 40 | # Ruby/Node 41 | vendor/bundle 42 | .bundle/ 43 | node_modules/ 44 | *.xcbkptlist 45 | -------------------------------------------------------------------------------- /CBInjection.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'CBInjection' 3 | s.version = '0.1.0' 4 | s.summary = 'A dependency injection library' 5 | s.description = 'A dependency injection library. Developed by Coinbase Wallet team.' 6 | 7 | s.homepage = 'https://github.com/CoinbaseWallet/CBInjection' 8 | s.license = { :type => "AGPL-3.0-only", :file => 'LICENSE' } 9 | s.author = { 'Coinbase' => 'developer@toshi.org' } 10 | s.source = { :git => 'https://github.com/CoinbaseWallet/CBInjection.git', :tag => s.version.to_s } 11 | s.social_media_url = 'https://twitter.com/coinbase' 12 | 13 | s.ios.deployment_target = '10.0' 14 | s.swift_version = '4.2' 15 | s.source_files = 'CBInjection/**/*.swift' 16 | end 17 | -------------------------------------------------------------------------------- /CBInjectionTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /CBInjection/Module/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | CBInjection 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | FMWK 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | 24 | 25 | -------------------------------------------------------------------------------- /CBInjection/Models/ViewControllerInjectionKey.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Coinbase Inc. See LICENSE 2 | 3 | import UIKit 4 | 5 | public class ViewControllerInjectionKey: InjectionKey { 6 | /// View controller modal presentation style 7 | let modalPresentationStyle: UIModalPresentationStyle 8 | 9 | public required init( 10 | uuid: String = NSUUID().uuidString, 11 | scope: InjectionScope, 12 | modalPresentationStyle: UIModalPresentationStyle = .fullScreen, 13 | closure: @escaping (Dependencies) throws -> UIViewController 14 | ) { 15 | self.modalPresentationStyle = modalPresentationStyle 16 | super.init(uuid: uuid, scope: scope, closure: closure) 17 | } 18 | 19 | public required init( 20 | uuid: String = NSUUID().uuidString, 21 | using injectionObjectType: DependencyInjection.Type, 22 | scope: InjectionScope, 23 | parameters: [InjectionParameterName: Any] = [:], 24 | modalPresentationStyle: UIModalPresentationStyle = .fullScreen 25 | ) { 26 | self.modalPresentationStyle = modalPresentationStyle 27 | super.init(uuid: uuid, using: injectionObjectType, scope: scope, parameters: parameters) 28 | } 29 | 30 | @available(*, unavailable) 31 | public required init( 32 | uuid: String = NSUUID().uuidString, 33 | scope: InjectionScope, 34 | closure: @escaping ((Dependencies) throws -> UIViewController) 35 | ) { 36 | fatalError("init(uuid:scope:closure:) has not been implemented") 37 | } 38 | 39 | @available(*, unavailable) 40 | public required init( 41 | uuid: String = NSUUID().uuidString, 42 | using injectionObjectType: DependencyInjection.Type, 43 | scope: InjectionScope, 44 | parameters: [InjectionParameterName : Any] = [:] 45 | ) { 46 | fatalError("init(uuid:using:scope:parameters:) has not been implemented") 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /CBInjection/Extensions/UIViewController+Injectables.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Coinbase Inc. See LICENSE 2 | 3 | import UIKit 4 | 5 | public extension UIViewController { 6 | /// Modally present view controller generated from given injection key 7 | /// 8 | /// - Parameters: 9 | /// - key: Key used to create view controller 10 | /// - animated: Animate present transition 11 | /// - modalPresentationStyle: Customize modal presentation 12 | /// - completion: Completion block called when transition completes 13 | /// 14 | /// - Returns: Instance of ViewController generated using provided injection key 15 | @discardableResult 16 | func present( 17 | _ key: ViewControllerInjectionKey, 18 | animated: Bool, 19 | completion: (() -> Void)? = nil 20 | ) -> UIViewController? { 21 | guard let viewController = try? Dependencies.shared.provide(key) else { 22 | assertionFailure("Unable to present view controller for key \(key)") 23 | return nil 24 | } 25 | 26 | viewController.modalPresentationStyle = key.modalPresentationStyle 27 | 28 | present(viewController, animated: animated, completion: completion) 29 | 30 | return viewController 31 | } 32 | 33 | /// Add child view controller using provided injection key 34 | /// 35 | /// - Parameters: 36 | /// - key: Key used to create view controller 37 | /// 38 | /// - Returns: Instance of ViewController generated using provided injection key 39 | func addChild(_ key: ViewControllerInjectionKey) -> UIViewController? { 40 | guard let viewController = try? Dependencies.shared.provide(key) else { 41 | assertionFailure("Unable to present view controller for key \(key)") 42 | return nil 43 | } 44 | 45 | viewController.willMove(toParent: self) 46 | addChild(viewController) 47 | view.addSubview(viewController.view) 48 | viewController.didMove(toParent: self) 49 | 50 | return viewController 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /CBInjection/Models/InjectionKey.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Coinbase Inc. See LICENSE 2 | 3 | import Foundation 4 | 5 | /// Represents and injection key used indentify a dependency. 6 | public class InjectionKey: InjectionKeys { 7 | /// Injection which contains the code for resolving a dependency 8 | let injection: DependencyInjection? 9 | 10 | /// Object scope. Singleton vs transient 11 | let scope: InjectionScope 12 | 13 | /// List of parameters to pass to injection conformer 14 | let parameters: [InjectionParameterName: Any] 15 | 16 | /// Closure which contains the code for resoliving dependency. A closure or injection can be used 17 | /// to resolve a dependency but not both 18 | let closure: ((Dependencies) throws -> T)? 19 | 20 | /// Injection-based constructor 21 | public required init( 22 | uuid: String = NSUUID().uuidString, 23 | using injectionObjectType: DependencyInjection.Type, 24 | scope: InjectionScope, 25 | parameters: [InjectionParameterName: Any] = [:] 26 | ) { 27 | injection = injectionObjectType.init() 28 | self.scope = scope 29 | self.parameters = parameters 30 | closure = nil 31 | super.init(uuid: uuid) 32 | } 33 | 34 | /// Closure-based constructor 35 | public required init( 36 | uuid: String = NSUUID().uuidString, 37 | scope: InjectionScope, 38 | closure: @escaping ((Dependencies) throws -> T) 39 | ) { 40 | self.scope = scope 41 | self.parameters = [:] 42 | self.closure = closure 43 | injection = nil 44 | super.init(uuid: uuid) 45 | } 46 | 47 | @available(*, unavailable) 48 | required init(uuid _: String) { 49 | fatalError("init(uuid:) has not been implemented") 50 | } 51 | } 52 | 53 | /// Static injection keys should be added to this class 54 | public class InjectionKeys: Hashable { 55 | /// Unique ID used to identify and cache singletons 56 | let uuid: String 57 | 58 | required init(uuid _: String) { 59 | uuid = NSUUID().uuidString 60 | } 61 | 62 | public func hash(into hasher: inout Hasher) { 63 | hasher.combine(uuid) 64 | } 65 | 66 | public static func == (lhs: InjectionKeys, rhs: InjectionKeys) -> Bool { 67 | return lhs.uuid == rhs.uuid 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /CBInjection/Dependency/Dependencies.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Coinbase Inc. See LICENSE 2 | 3 | import Foundation 4 | 5 | /// Simple dependency injection framework. Note: This doesn't resolve circular reference dependencies. 6 | public final class Dependencies { 7 | public static let shared = Dependencies() 8 | 9 | /// Makes sure singleton access is thread safe 10 | private let singletonLock = NSRecursiveLock() 11 | 12 | /// Holds on to cached singletons 13 | private var cache = [InjectionKeys: Any]() 14 | 15 | /// Keep internal. Used to cache injection key overrides in unit tests 16 | internal var injectionKeyOverrides = [InjectionKeys: InjectionKeys]() 17 | 18 | /// Keep internal. Used to override injection keys in unit tests 19 | /// 20 | /// - Parameters: 21 | /// - key: The original key to override 22 | /// - overrideKey: The override injection key 23 | internal func replace(key: InjectionKey, with overrideKey: InjectionKey) { 24 | injectionKeyOverrides[key] = overrideKey 25 | } 26 | 27 | /// Get injection for given injection key 28 | /// 29 | /// - Parameters: 30 | /// - injectionKey: Key specifying type of injection 31 | /// 32 | /// - Returns: Instance of the requested dependency or an error is thrown 33 | public func provide(_ injectionKey: InjectionKey) throws -> T { 34 | let key = (injectionKeyOverrides[injectionKey] as? InjectionKey) ?? injectionKey 35 | 36 | switch key.scope { 37 | case .singleton: 38 | singletonLock.lock() 39 | defer { singletonLock.unlock() } 40 | 41 | if let instance = cache[key] as? T { 42 | return instance 43 | } 44 | 45 | if let instance = try self.resolve(key) { 46 | cache[key] = instance 47 | return instance 48 | } 49 | case .transient: 50 | if let instance = try self.resolve(key) { 51 | return instance 52 | } 53 | } 54 | 55 | throw DependenciesError.unableToResolveDependency(key) 56 | } 57 | 58 | /// Destroy all dependencies 59 | public func destroy() { 60 | cache.removeAll() 61 | } 62 | 63 | // MARK: helpers 64 | 65 | func resolve(_ key: InjectionKey) throws -> T? { 66 | if let closure = key.closure { 67 | return try closure(self) 68 | } else if let instance = try key.injection?.provide(using: self, parameters: key.parameters) { 69 | return instance 70 | } 71 | 72 | throw DependenciesError.unableToResolveDependency(key) 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /CBInjection/Extensions/UINavigationController+Injectables.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Coinbase Inc. See LICENSE 2 | 3 | import UIKit 4 | 5 | public extension UINavigationController { 6 | /// Initialize the navigation controller with an injected root view controller 7 | /// 8 | /// - Parameter rootViewControllerKey: the injection key for the root view controller 9 | convenience init(rootViewControllerKey: ViewControllerInjectionKey) { 10 | guard let viewController = try? Dependencies.shared.provide(rootViewControllerKey) else { 11 | fatalError("View controller not found") 12 | } 13 | 14 | self.init(rootViewController: viewController) 15 | } 16 | 17 | /// Push view controller generated from given injection key 18 | /// 19 | /// - Parameters: 20 | /// - key: Key used to create view controller 21 | /// - animated: Animate push transition 22 | /// 23 | /// - Returns: Instance of ViewController generated using provided injection key 24 | @discardableResult 25 | func pushViewController(_ key: ViewControllerInjectionKey, animated: Bool) -> UIViewController? { 26 | guard let viewController = try? Dependencies.shared.provide(key) else { 27 | assertionFailure("Unable to push view controller for key \(key)") 28 | return nil 29 | } 30 | 31 | pushViewController(viewController, animated: animated) 32 | 33 | return viewController 34 | } 35 | 36 | /// Set the navigation controller's view controllers from their injection keys 37 | /// 38 | /// - Parameters: 39 | /// - keys: Injection keys for the view controllers 40 | /// - animated: true if the transition should be animated 41 | func setViewControllers(_ keys: [ViewControllerInjectionKey], animated: Bool) { 42 | let viewControllers = keys.compactMap { key -> UIViewController? in 43 | guard let viewController: UIViewController = try? Dependencies.shared.provide(key) else { 44 | assertionFailure("Unable to push view controller for key \(key)") 45 | return nil 46 | } 47 | 48 | return viewController 49 | } 50 | 51 | setViewControllers(viewControllers, animated: animated) 52 | } 53 | 54 | /// Set the navigation controllers root view controller using provided injection key 55 | /// 56 | /// - Parameters: 57 | /// - key: Injection key for the view controller 58 | /// - animated: true if the transition should be animated 59 | /// 60 | /// - Returns: Instance of ViewController generated using provided injection key 61 | func setRootViewController(_ key: ViewControllerInjectionKey, animated: Bool) -> UIViewController? { 62 | guard let viewController = try? Dependencies.shared.provide(key) else { 63 | assertionFailure("Unable to push view controller for key \(key)") 64 | return nil 65 | } 66 | 67 | setViewControllers([viewController], animated: animated) 68 | 69 | return viewController 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /CBInjection.xcodeproj/xcshareddata/xcschemes/CBInjection.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /CBInjectionTests/DependenciesTests.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Coinbase Inc. See LICENSE 2 | 3 | @testable import CBInjection 4 | import XCTest 5 | 6 | private let expectedName = "Notorious B.I.G." 7 | private let expecetdID = 123 8 | 9 | class DependenciesTests: XCTestCase { 10 | func testSingleton() throws { 11 | let actual = try Dependencies.shared.provide(.dummySingleton) 12 | let actual2 = try Dependencies.shared.provide(.dummySingleton) 13 | 14 | XCTAssertEqual(expecetdID, actual.id) 15 | XCTAssertEqual(expectedName, actual.name) 16 | 17 | XCTAssertEqual(expecetdID, actual2.id) 18 | XCTAssertEqual(expectedName, actual2.name) 19 | 20 | XCTAssertEqual(actual.uuid, actual2.uuid) 21 | } 22 | 23 | func testTransient() throws { 24 | let actual = try Dependencies.shared.provide(.dummyTransient) 25 | let actual2 = try Dependencies.shared.provide(.dummyTransient) 26 | 27 | XCTAssertEqual(expecetdID, actual.id) 28 | XCTAssertEqual(expectedName, actual.name) 29 | 30 | XCTAssertEqual(expecetdID, actual2.id) 31 | XCTAssertEqual(expectedName, actual2.name) 32 | 33 | XCTAssertNotEqual(actual.uuid, actual2.uuid) 34 | } 35 | 36 | func testInjectedTransient() throws { 37 | let actual = try Dependencies.shared.provide(.dummyInjectedTransient) 38 | let actual2 = try Dependencies.shared.provide(.dummyInjectedTransient) 39 | 40 | XCTAssertEqual(expecetdID, actual.id) 41 | XCTAssertEqual(expectedName, actual.name) 42 | XCTAssertEqual(expecetdID, actual.transientDep.id) 43 | XCTAssertEqual(expectedName, actual.transientDep.name) 44 | 45 | XCTAssertEqual(expecetdID, actual2.id) 46 | XCTAssertEqual(expectedName, actual2.name) 47 | XCTAssertEqual(expecetdID, actual2.transientDep.id) 48 | XCTAssertEqual(expectedName, actual2.transientDep.name) 49 | 50 | XCTAssertNotEqual(actual.uuid, actual2.uuid) 51 | } 52 | 53 | func testInjectedTransientInSingleton() throws { 54 | let actual = try Dependencies.shared.provide(.dummyInjectedTransientInSingleton) 55 | let actual2 = try Dependencies.shared.provide(.dummyInjectedTransientInSingleton) 56 | 57 | XCTAssertEqual(expecetdID, actual.id) 58 | XCTAssertEqual(expectedName, actual.name) 59 | XCTAssertEqual(expecetdID, actual.transientDep.id) 60 | XCTAssertEqual(expectedName, actual.transientDep.name) 61 | 62 | XCTAssertEqual(expecetdID, actual2.id) 63 | XCTAssertEqual(expectedName, actual2.name) 64 | XCTAssertEqual(expecetdID, actual2.transientDep.id) 65 | XCTAssertEqual(expectedName, actual2.transientDep.name) 66 | 67 | XCTAssertEqual(actual.uuid, actual2.uuid) 68 | XCTAssertEqual(actual.transientDep.uuid, actual2.transientDep.uuid) 69 | XCTAssertEqual(actual.transientDep.id, actual2.transientDep.id) 70 | XCTAssertEqual(actual.transientDep.name, actual2.transientDep.name) 71 | } 72 | 73 | func testInjectedClosureTransientInSingleton() throws { 74 | let actual = try Dependencies.shared.provide(.closureStyleSingletontKey) 75 | let actual2 = try Dependencies.shared.provide(.closureStyleSingletontKey) 76 | 77 | XCTAssertEqual(expecetdID, actual.id) 78 | XCTAssertEqual(expectedName, actual.name) 79 | XCTAssertEqual(expecetdID, actual.transientDep.id) 80 | XCTAssertEqual(expectedName, actual.transientDep.name) 81 | 82 | XCTAssertEqual(expecetdID, actual2.id) 83 | XCTAssertEqual(expectedName, actual2.name) 84 | XCTAssertEqual(expecetdID, actual2.transientDep.id) 85 | XCTAssertEqual(expectedName, actual2.transientDep.name) 86 | 87 | XCTAssertEqual(actual.uuid, actual2.uuid) 88 | XCTAssertEqual(actual.transientDep.uuid, actual2.transientDep.uuid) 89 | XCTAssertEqual(actual.transientDep.id, actual2.transientDep.id) 90 | XCTAssertEqual(actual.transientDep.name, actual2.transientDep.name) 91 | } 92 | 93 | func testInjectedClosureTransient() throws { 94 | let actual = try Dependencies.shared.provide(.closureStyleTransientKey) 95 | let actual2 = try Dependencies.shared.provide(.closureStyleTransientKey) 96 | 97 | XCTAssertEqual(expecetdID, actual.id) 98 | XCTAssertEqual(expectedName, actual.name) 99 | XCTAssertEqual(expecetdID, actual.transientDep.id) 100 | XCTAssertEqual(expectedName, actual.transientDep.name) 101 | 102 | XCTAssertEqual(expecetdID, actual2.id) 103 | XCTAssertEqual(expectedName, actual2.name) 104 | XCTAssertEqual(expecetdID, actual2.transientDep.id) 105 | XCTAssertEqual(expectedName, actual2.transientDep.name) 106 | 107 | XCTAssertNotEqual(actual.uuid, actual2.uuid) 108 | } 109 | 110 | func testInjectioReplacement() throws { 111 | let deps = Dependencies() 112 | let expectedResolvedString = "Hello World" 113 | let originalKey = InjectionKey(scope: .transient) { _ in 114 | return "OriginalKey" 115 | } 116 | 117 | let replacementKey = InjectionKey(scope: .transient) { _ in 118 | return expectedResolvedString 119 | } 120 | 121 | deps.replace(key: originalKey, with: replacementKey) 122 | 123 | let actual = try deps.provide(originalKey) 124 | 125 | XCTAssertEqual(expectedResolvedString, actual) 126 | } 127 | } 128 | 129 | private extension InjectionKeys { 130 | static let dummySingleton = InjectionKey( 131 | using: DummyDependencyInjection.self, 132 | scope: .singleton 133 | ) 134 | 135 | static let dummyTransient = InjectionKey( 136 | using: DummyDependencyInjection.self, 137 | scope: .transient 138 | ) 139 | 140 | static let dummyInjectedTransient = InjectionKey( 141 | using: DummyInjectedTransientInjection.self, 142 | scope: .transient 143 | ) 144 | 145 | static let dummyInjectedTransientInSingleton = InjectionKey( 146 | using: DummyInjectedTransientInjection.self, 147 | scope: .singleton 148 | ) 149 | 150 | static let closureStyleTransientKey = InjectionKey(scope: .transient) { dependencies in 151 | let dep = try dependencies.provide(.dummyTransient) 152 | return DummyInjectedTransient(id: expecetdID, name: expectedName, uuid: UUID().uuidString, transientDep: dep) 153 | } 154 | 155 | static let closureStyleSingletontKey = InjectionKey(scope: .singleton) { dependencies in 156 | let dep = try dependencies.provide(.dummyTransient) 157 | return DummyInjectedTransient(id: expecetdID, name: expectedName, uuid: UUID().uuidString, transientDep: dep) 158 | } 159 | } 160 | 161 | struct DummyInjectedTransient { 162 | let id: Int 163 | let name: String 164 | let uuid: String 165 | let transientDep: DummyDependency 166 | } 167 | 168 | struct DummyDependency { 169 | let id: Int 170 | let name: String 171 | let uuid: String 172 | } 173 | 174 | final class DummyDependencyInjection: DependencyInjection { 175 | override func provide(using _: Dependencies, parameters: [InjectionParameterName: Any]) throws -> DummyDependency { 176 | return DummyDependency(id: expecetdID, name: expectedName, uuid: UUID().uuidString) 177 | } 178 | } 179 | 180 | final class DummyInjectedTransientInjection: DependencyInjection { 181 | override func provide( 182 | using dependencies: Dependencies, 183 | parameters _: [InjectionParameterName: Any] 184 | ) throws -> DummyInjectedTransient { 185 | let dep = try dependencies.provide(.dummyTransient) 186 | return DummyInjectedTransient(id: expecetdID, name: expectedName, uuid: UUID().uuidString, transientDep: dep) 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /CBInjection.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | D30B80852367A32000D3D508 /* ViewControllerInjectionKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = D30B80842367A32000D3D508 /* ViewControllerInjectionKey.swift */; }; 11 | E74DE55C22333E83008CC5EE /* CBInjection.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E74DE55222333E83008CC5EE /* CBInjection.framework */; }; 12 | E74DE56122333E83008CC5EE /* DependenciesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E74DE56022333E83008CC5EE /* DependenciesTests.swift */; }; 13 | E74DE57D22333F9D008CC5EE /* InjectionParameterName.swift in Sources */ = {isa = PBXBuildFile; fileRef = E74DE56D22333F9D008CC5EE /* InjectionParameterName.swift */; }; 14 | E74DE57E22333F9D008CC5EE /* InjectionKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = E74DE56E22333F9D008CC5EE /* InjectionKey.swift */; }; 15 | E74DE57F22333F9D008CC5EE /* InjectionScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = E74DE56F22333F9D008CC5EE /* InjectionScope.swift */; }; 16 | E74DE58022333F9D008CC5EE /* CBInjection.h in Headers */ = {isa = PBXBuildFile; fileRef = E74DE57122333F9D008CC5EE /* CBInjection.h */; settings = {ATTRIBUTES = (Public, ); }; }; 17 | E74DE58222333F9D008CC5EE /* DependenciesError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E74DE57422333F9D008CC5EE /* DependenciesError.swift */; }; 18 | E74DE58322333F9D008CC5EE /* UINavigationController+Injectables.swift in Sources */ = {isa = PBXBuildFile; fileRef = E74DE57622333F9D008CC5EE /* UINavigationController+Injectables.swift */; }; 19 | E74DE58422333F9D008CC5EE /* UIViewController+Injectables.swift in Sources */ = {isa = PBXBuildFile; fileRef = E74DE57722333F9D008CC5EE /* UIViewController+Injectables.swift */; }; 20 | E74DE58522333F9D008CC5EE /* DependencyInjection.swift in Sources */ = {isa = PBXBuildFile; fileRef = E74DE57922333F9D008CC5EE /* DependencyInjection.swift */; }; 21 | E74DE58722333F9D008CC5EE /* Dependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = E74DE57C22333F9D008CC5EE /* Dependencies.swift */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXContainerItemProxy section */ 25 | E74DE55D22333E83008CC5EE /* PBXContainerItemProxy */ = { 26 | isa = PBXContainerItemProxy; 27 | containerPortal = E74DE54922333E83008CC5EE /* Project object */; 28 | proxyType = 1; 29 | remoteGlobalIDString = E74DE55122333E83008CC5EE; 30 | remoteInfo = CBInjections; 31 | }; 32 | /* End PBXContainerItemProxy section */ 33 | 34 | /* Begin PBXFileReference section */ 35 | D30B80842367A32000D3D508 /* ViewControllerInjectionKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewControllerInjectionKey.swift; sourceTree = ""; }; 36 | E74DE55222333E83008CC5EE /* CBInjection.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CBInjection.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 37 | E74DE55B22333E83008CC5EE /* CBInjectionTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CBInjectionTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | E74DE56022333E83008CC5EE /* DependenciesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DependenciesTests.swift; sourceTree = ""; }; 39 | E74DE56222333E83008CC5EE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 40 | E74DE56D22333F9D008CC5EE /* InjectionParameterName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InjectionParameterName.swift; sourceTree = ""; }; 41 | E74DE56E22333F9D008CC5EE /* InjectionKey.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InjectionKey.swift; sourceTree = ""; }; 42 | E74DE56F22333F9D008CC5EE /* InjectionScope.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InjectionScope.swift; sourceTree = ""; }; 43 | E74DE57122333F9D008CC5EE /* CBInjection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CBInjection.h; sourceTree = ""; }; 44 | E74DE57222333F9D008CC5EE /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 45 | E74DE57422333F9D008CC5EE /* DependenciesError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DependenciesError.swift; sourceTree = ""; }; 46 | E74DE57622333F9D008CC5EE /* UINavigationController+Injectables.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Injectables.swift"; sourceTree = ""; }; 47 | E74DE57722333F9D008CC5EE /* UIViewController+Injectables.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+Injectables.swift"; sourceTree = ""; }; 48 | E74DE57922333F9D008CC5EE /* DependencyInjection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DependencyInjection.swift; sourceTree = ""; }; 49 | E74DE57C22333F9D008CC5EE /* Dependencies.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Dependencies.swift; sourceTree = ""; }; 50 | /* End PBXFileReference section */ 51 | 52 | /* Begin PBXFrameworksBuildPhase section */ 53 | E74DE54F22333E83008CC5EE /* Frameworks */ = { 54 | isa = PBXFrameworksBuildPhase; 55 | buildActionMask = 2147483647; 56 | files = ( 57 | ); 58 | runOnlyForDeploymentPostprocessing = 0; 59 | }; 60 | E74DE55822333E83008CC5EE /* Frameworks */ = { 61 | isa = PBXFrameworksBuildPhase; 62 | buildActionMask = 2147483647; 63 | files = ( 64 | E74DE55C22333E83008CC5EE /* CBInjection.framework in Frameworks */, 65 | ); 66 | runOnlyForDeploymentPostprocessing = 0; 67 | }; 68 | /* End PBXFrameworksBuildPhase section */ 69 | 70 | /* Begin PBXGroup section */ 71 | E74DE54822333E83008CC5EE = { 72 | isa = PBXGroup; 73 | children = ( 74 | E74DE55422333E83008CC5EE /* CBInjection */, 75 | E74DE55F22333E83008CC5EE /* CBInjectionTests */, 76 | E74DE55322333E83008CC5EE /* Products */, 77 | ); 78 | sourceTree = ""; 79 | }; 80 | E74DE55322333E83008CC5EE /* Products */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | E74DE55222333E83008CC5EE /* CBInjection.framework */, 84 | E74DE55B22333E83008CC5EE /* CBInjectionTests.xctest */, 85 | ); 86 | name = Products; 87 | sourceTree = ""; 88 | }; 89 | E74DE55422333E83008CC5EE /* CBInjection */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | E74DE57B22333F9D008CC5EE /* Dependency */, 93 | E74DE57322333F9D008CC5EE /* Errors */, 94 | E74DE57522333F9D008CC5EE /* Extensions */, 95 | E74DE56C22333F9D008CC5EE /* Models */, 96 | E74DE57022333F9D008CC5EE /* Module */, 97 | ); 98 | path = CBInjection; 99 | sourceTree = ""; 100 | }; 101 | E74DE55F22333E83008CC5EE /* CBInjectionTests */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | E74DE56022333E83008CC5EE /* DependenciesTests.swift */, 105 | E74DE56222333E83008CC5EE /* Info.plist */, 106 | ); 107 | path = CBInjectionTests; 108 | sourceTree = ""; 109 | }; 110 | E74DE56C22333F9D008CC5EE /* Models */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | E74DE57922333F9D008CC5EE /* DependencyInjection.swift */, 114 | E74DE56D22333F9D008CC5EE /* InjectionParameterName.swift */, 115 | E74DE56E22333F9D008CC5EE /* InjectionKey.swift */, 116 | E74DE56F22333F9D008CC5EE /* InjectionScope.swift */, 117 | D30B80842367A32000D3D508 /* ViewControllerInjectionKey.swift */, 118 | ); 119 | path = Models; 120 | sourceTree = ""; 121 | }; 122 | E74DE57022333F9D008CC5EE /* Module */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | E74DE57122333F9D008CC5EE /* CBInjection.h */, 126 | E74DE57222333F9D008CC5EE /* Info.plist */, 127 | ); 128 | path = Module; 129 | sourceTree = ""; 130 | }; 131 | E74DE57322333F9D008CC5EE /* Errors */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | E74DE57422333F9D008CC5EE /* DependenciesError.swift */, 135 | ); 136 | path = Errors; 137 | sourceTree = ""; 138 | }; 139 | E74DE57522333F9D008CC5EE /* Extensions */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | E74DE57622333F9D008CC5EE /* UINavigationController+Injectables.swift */, 143 | E74DE57722333F9D008CC5EE /* UIViewController+Injectables.swift */, 144 | ); 145 | path = Extensions; 146 | sourceTree = ""; 147 | }; 148 | E74DE57B22333F9D008CC5EE /* Dependency */ = { 149 | isa = PBXGroup; 150 | children = ( 151 | E74DE57C22333F9D008CC5EE /* Dependencies.swift */, 152 | ); 153 | path = Dependency; 154 | sourceTree = ""; 155 | }; 156 | /* End PBXGroup section */ 157 | 158 | /* Begin PBXHeadersBuildPhase section */ 159 | E74DE54D22333E83008CC5EE /* Headers */ = { 160 | isa = PBXHeadersBuildPhase; 161 | buildActionMask = 2147483647; 162 | files = ( 163 | E74DE58022333F9D008CC5EE /* CBInjection.h in Headers */, 164 | ); 165 | runOnlyForDeploymentPostprocessing = 0; 166 | }; 167 | /* End PBXHeadersBuildPhase section */ 168 | 169 | /* Begin PBXNativeTarget section */ 170 | E74DE55122333E83008CC5EE /* CBInjection */ = { 171 | isa = PBXNativeTarget; 172 | buildConfigurationList = E74DE56622333E83008CC5EE /* Build configuration list for PBXNativeTarget "CBInjection" */; 173 | buildPhases = ( 174 | E74DE54D22333E83008CC5EE /* Headers */, 175 | E74DE54E22333E83008CC5EE /* Sources */, 176 | E74DE54F22333E83008CC5EE /* Frameworks */, 177 | E74DE55022333E83008CC5EE /* Resources */, 178 | ); 179 | buildRules = ( 180 | ); 181 | dependencies = ( 182 | ); 183 | name = CBInjection; 184 | productName = CBInjections; 185 | productReference = E74DE55222333E83008CC5EE /* CBInjection.framework */; 186 | productType = "com.apple.product-type.framework"; 187 | }; 188 | E74DE55A22333E83008CC5EE /* CBInjectionTests */ = { 189 | isa = PBXNativeTarget; 190 | buildConfigurationList = E74DE56922333E83008CC5EE /* Build configuration list for PBXNativeTarget "CBInjectionTests" */; 191 | buildPhases = ( 192 | E74DE55722333E83008CC5EE /* Sources */, 193 | E74DE55822333E83008CC5EE /* Frameworks */, 194 | E74DE55922333E83008CC5EE /* Resources */, 195 | ); 196 | buildRules = ( 197 | ); 198 | dependencies = ( 199 | E74DE55E22333E83008CC5EE /* PBXTargetDependency */, 200 | ); 201 | name = CBInjectionTests; 202 | productName = CBInjectionsTests; 203 | productReference = E74DE55B22333E83008CC5EE /* CBInjectionTests.xctest */; 204 | productType = "com.apple.product-type.bundle.unit-test"; 205 | }; 206 | /* End PBXNativeTarget section */ 207 | 208 | /* Begin PBXProject section */ 209 | E74DE54922333E83008CC5EE /* Project object */ = { 210 | isa = PBXProject; 211 | attributes = { 212 | LastSwiftUpdateCheck = 1010; 213 | LastUpgradeCheck = 1010; 214 | ORGANIZATIONNAME = "Coinbase Inc"; 215 | TargetAttributes = { 216 | E74DE55122333E83008CC5EE = { 217 | CreatedOnToolsVersion = 10.1; 218 | }; 219 | E74DE55A22333E83008CC5EE = { 220 | CreatedOnToolsVersion = 10.1; 221 | }; 222 | }; 223 | }; 224 | buildConfigurationList = E74DE54C22333E83008CC5EE /* Build configuration list for PBXProject "CBInjection" */; 225 | compatibilityVersion = "Xcode 9.3"; 226 | developmentRegion = en; 227 | hasScannedForEncodings = 0; 228 | knownRegions = ( 229 | en, 230 | ); 231 | mainGroup = E74DE54822333E83008CC5EE; 232 | productRefGroup = E74DE55322333E83008CC5EE /* Products */; 233 | projectDirPath = ""; 234 | projectRoot = ""; 235 | targets = ( 236 | E74DE55122333E83008CC5EE /* CBInjection */, 237 | E74DE55A22333E83008CC5EE /* CBInjectionTests */, 238 | ); 239 | }; 240 | /* End PBXProject section */ 241 | 242 | /* Begin PBXResourcesBuildPhase section */ 243 | E74DE55022333E83008CC5EE /* Resources */ = { 244 | isa = PBXResourcesBuildPhase; 245 | buildActionMask = 2147483647; 246 | files = ( 247 | ); 248 | runOnlyForDeploymentPostprocessing = 0; 249 | }; 250 | E74DE55922333E83008CC5EE /* Resources */ = { 251 | isa = PBXResourcesBuildPhase; 252 | buildActionMask = 2147483647; 253 | files = ( 254 | ); 255 | runOnlyForDeploymentPostprocessing = 0; 256 | }; 257 | /* End PBXResourcesBuildPhase section */ 258 | 259 | /* Begin PBXSourcesBuildPhase section */ 260 | E74DE54E22333E83008CC5EE /* Sources */ = { 261 | isa = PBXSourcesBuildPhase; 262 | buildActionMask = 2147483647; 263 | files = ( 264 | E74DE58322333F9D008CC5EE /* UINavigationController+Injectables.swift in Sources */, 265 | E74DE57D22333F9D008CC5EE /* InjectionParameterName.swift in Sources */, 266 | E74DE57F22333F9D008CC5EE /* InjectionScope.swift in Sources */, 267 | D30B80852367A32000D3D508 /* ViewControllerInjectionKey.swift in Sources */, 268 | E74DE58722333F9D008CC5EE /* Dependencies.swift in Sources */, 269 | E74DE58422333F9D008CC5EE /* UIViewController+Injectables.swift in Sources */, 270 | E74DE57E22333F9D008CC5EE /* InjectionKey.swift in Sources */, 271 | E74DE58522333F9D008CC5EE /* DependencyInjection.swift in Sources */, 272 | E74DE58222333F9D008CC5EE /* DependenciesError.swift in Sources */, 273 | ); 274 | runOnlyForDeploymentPostprocessing = 0; 275 | }; 276 | E74DE55722333E83008CC5EE /* Sources */ = { 277 | isa = PBXSourcesBuildPhase; 278 | buildActionMask = 2147483647; 279 | files = ( 280 | E74DE56122333E83008CC5EE /* DependenciesTests.swift in Sources */, 281 | ); 282 | runOnlyForDeploymentPostprocessing = 0; 283 | }; 284 | /* End PBXSourcesBuildPhase section */ 285 | 286 | /* Begin PBXTargetDependency section */ 287 | E74DE55E22333E83008CC5EE /* PBXTargetDependency */ = { 288 | isa = PBXTargetDependency; 289 | target = E74DE55122333E83008CC5EE /* CBInjection */; 290 | targetProxy = E74DE55D22333E83008CC5EE /* PBXContainerItemProxy */; 291 | }; 292 | /* End PBXTargetDependency section */ 293 | 294 | /* Begin XCBuildConfiguration section */ 295 | E74DE56422333E83008CC5EE /* Debug */ = { 296 | isa = XCBuildConfiguration; 297 | buildSettings = { 298 | ALWAYS_SEARCH_USER_PATHS = NO; 299 | CLANG_ANALYZER_NONNULL = YES; 300 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 301 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 302 | CLANG_CXX_LIBRARY = "libc++"; 303 | CLANG_ENABLE_MODULES = YES; 304 | CLANG_ENABLE_OBJC_ARC = YES; 305 | CLANG_ENABLE_OBJC_WEAK = YES; 306 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 307 | CLANG_WARN_BOOL_CONVERSION = YES; 308 | CLANG_WARN_COMMA = YES; 309 | CLANG_WARN_CONSTANT_CONVERSION = YES; 310 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 311 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 312 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 313 | CLANG_WARN_EMPTY_BODY = YES; 314 | CLANG_WARN_ENUM_CONVERSION = YES; 315 | CLANG_WARN_INFINITE_RECURSION = YES; 316 | CLANG_WARN_INT_CONVERSION = YES; 317 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 318 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 319 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 320 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 321 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 322 | CLANG_WARN_STRICT_PROTOTYPES = YES; 323 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 324 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 325 | CLANG_WARN_UNREACHABLE_CODE = YES; 326 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 327 | CODE_SIGN_IDENTITY = "iPhone Developer"; 328 | COPY_PHASE_STRIP = NO; 329 | CURRENT_PROJECT_VERSION = 1; 330 | DEBUG_INFORMATION_FORMAT = dwarf; 331 | ENABLE_STRICT_OBJC_MSGSEND = YES; 332 | ENABLE_TESTABILITY = YES; 333 | GCC_C_LANGUAGE_STANDARD = gnu11; 334 | GCC_DYNAMIC_NO_PIC = NO; 335 | GCC_NO_COMMON_BLOCKS = YES; 336 | GCC_OPTIMIZATION_LEVEL = 0; 337 | GCC_PREPROCESSOR_DEFINITIONS = ( 338 | "DEBUG=1", 339 | "$(inherited)", 340 | ); 341 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 342 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 343 | GCC_WARN_UNDECLARED_SELECTOR = YES; 344 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 345 | GCC_WARN_UNUSED_FUNCTION = YES; 346 | GCC_WARN_UNUSED_VARIABLE = YES; 347 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 348 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 349 | MTL_FAST_MATH = YES; 350 | ONLY_ACTIVE_ARCH = YES; 351 | SDKROOT = iphoneos; 352 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 353 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 354 | SWIFT_VERSION = 4.2; 355 | VERSIONING_SYSTEM = "apple-generic"; 356 | VERSION_INFO_PREFIX = ""; 357 | }; 358 | name = Debug; 359 | }; 360 | E74DE56522333E83008CC5EE /* Release */ = { 361 | isa = XCBuildConfiguration; 362 | buildSettings = { 363 | ALWAYS_SEARCH_USER_PATHS = NO; 364 | CLANG_ANALYZER_NONNULL = YES; 365 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 366 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 367 | CLANG_CXX_LIBRARY = "libc++"; 368 | CLANG_ENABLE_MODULES = YES; 369 | CLANG_ENABLE_OBJC_ARC = YES; 370 | CLANG_ENABLE_OBJC_WEAK = YES; 371 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 372 | CLANG_WARN_BOOL_CONVERSION = YES; 373 | CLANG_WARN_COMMA = YES; 374 | CLANG_WARN_CONSTANT_CONVERSION = YES; 375 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 376 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 377 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 378 | CLANG_WARN_EMPTY_BODY = YES; 379 | CLANG_WARN_ENUM_CONVERSION = YES; 380 | CLANG_WARN_INFINITE_RECURSION = YES; 381 | CLANG_WARN_INT_CONVERSION = YES; 382 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 383 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 384 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 385 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 386 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 387 | CLANG_WARN_STRICT_PROTOTYPES = YES; 388 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 389 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 390 | CLANG_WARN_UNREACHABLE_CODE = YES; 391 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 392 | CODE_SIGN_IDENTITY = "iPhone Developer"; 393 | COPY_PHASE_STRIP = NO; 394 | CURRENT_PROJECT_VERSION = 1; 395 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 396 | ENABLE_NS_ASSERTIONS = NO; 397 | ENABLE_STRICT_OBJC_MSGSEND = YES; 398 | GCC_C_LANGUAGE_STANDARD = gnu11; 399 | GCC_NO_COMMON_BLOCKS = YES; 400 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 401 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 402 | GCC_WARN_UNDECLARED_SELECTOR = YES; 403 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 404 | GCC_WARN_UNUSED_FUNCTION = YES; 405 | GCC_WARN_UNUSED_VARIABLE = YES; 406 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 407 | MTL_ENABLE_DEBUG_INFO = NO; 408 | MTL_FAST_MATH = YES; 409 | SDKROOT = iphoneos; 410 | SWIFT_COMPILATION_MODE = wholemodule; 411 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 412 | SWIFT_VERSION = 4.2; 413 | VALIDATE_PRODUCT = YES; 414 | VERSIONING_SYSTEM = "apple-generic"; 415 | VERSION_INFO_PREFIX = ""; 416 | }; 417 | name = Release; 418 | }; 419 | E74DE56722333E83008CC5EE /* Debug */ = { 420 | isa = XCBuildConfiguration; 421 | buildSettings = { 422 | CODE_SIGN_IDENTITY = ""; 423 | CODE_SIGN_STYLE = Automatic; 424 | DEFINES_MODULE = YES; 425 | DYLIB_COMPATIBILITY_VERSION = 1; 426 | DYLIB_CURRENT_VERSION = 1; 427 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 428 | INFOPLIST_FILE = "$(SRCROOT)/CBInjection/Module/Info.plist"; 429 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 430 | IPHONEOS_DEPLOYMENT_TARGET = 10; 431 | LD_RUNPATH_SEARCH_PATHS = ( 432 | "$(inherited)", 433 | "@executable_path/Frameworks", 434 | "@loader_path/Frameworks", 435 | ); 436 | PRODUCT_BUNDLE_IDENTIFIER = com.coinbase.wallet.injection; 437 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 438 | SKIP_INSTALL = YES; 439 | SWIFT_VERSION = 4.2; 440 | TARGETED_DEVICE_FAMILY = "1,2"; 441 | }; 442 | name = Debug; 443 | }; 444 | E74DE56822333E83008CC5EE /* Release */ = { 445 | isa = XCBuildConfiguration; 446 | buildSettings = { 447 | CODE_SIGN_IDENTITY = ""; 448 | CODE_SIGN_STYLE = Automatic; 449 | DEFINES_MODULE = YES; 450 | DYLIB_COMPATIBILITY_VERSION = 1; 451 | DYLIB_CURRENT_VERSION = 1; 452 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 453 | INFOPLIST_FILE = "$(SRCROOT)/CBInjection/Module/Info.plist"; 454 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 455 | IPHONEOS_DEPLOYMENT_TARGET = 10; 456 | LD_RUNPATH_SEARCH_PATHS = ( 457 | "$(inherited)", 458 | "@executable_path/Frameworks", 459 | "@loader_path/Frameworks", 460 | ); 461 | PRODUCT_BUNDLE_IDENTIFIER = com.coinbase.wallet.injection; 462 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 463 | SKIP_INSTALL = YES; 464 | SWIFT_VERSION = 4.2; 465 | TARGETED_DEVICE_FAMILY = "1,2"; 466 | }; 467 | name = Release; 468 | }; 469 | E74DE56A22333E83008CC5EE /* Debug */ = { 470 | isa = XCBuildConfiguration; 471 | buildSettings = { 472 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 473 | CODE_SIGN_STYLE = Automatic; 474 | INFOPLIST_FILE = CBInjectionTests/Info.plist; 475 | LD_RUNPATH_SEARCH_PATHS = ( 476 | "$(inherited)", 477 | "@executable_path/Frameworks", 478 | "@loader_path/Frameworks", 479 | ); 480 | PRODUCT_BUNDLE_IDENTIFIER = com.coinbase.wallet.injectiontests; 481 | PRODUCT_NAME = "$(TARGET_NAME)"; 482 | SWIFT_VERSION = 4.2; 483 | TARGETED_DEVICE_FAMILY = "1,2"; 484 | }; 485 | name = Debug; 486 | }; 487 | E74DE56B22333E83008CC5EE /* Release */ = { 488 | isa = XCBuildConfiguration; 489 | buildSettings = { 490 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 491 | CODE_SIGN_STYLE = Automatic; 492 | INFOPLIST_FILE = CBInjectionTests/Info.plist; 493 | LD_RUNPATH_SEARCH_PATHS = ( 494 | "$(inherited)", 495 | "@executable_path/Frameworks", 496 | "@loader_path/Frameworks", 497 | ); 498 | PRODUCT_BUNDLE_IDENTIFIER = com.coinbase.wallet.injectiontests; 499 | PRODUCT_NAME = "$(TARGET_NAME)"; 500 | SWIFT_VERSION = 4.2; 501 | TARGETED_DEVICE_FAMILY = "1,2"; 502 | }; 503 | name = Release; 504 | }; 505 | /* End XCBuildConfiguration section */ 506 | 507 | /* Begin XCConfigurationList section */ 508 | E74DE54C22333E83008CC5EE /* Build configuration list for PBXProject "CBInjection" */ = { 509 | isa = XCConfigurationList; 510 | buildConfigurations = ( 511 | E74DE56422333E83008CC5EE /* Debug */, 512 | E74DE56522333E83008CC5EE /* Release */, 513 | ); 514 | defaultConfigurationIsVisible = 0; 515 | defaultConfigurationName = Release; 516 | }; 517 | E74DE56622333E83008CC5EE /* Build configuration list for PBXNativeTarget "CBInjection" */ = { 518 | isa = XCConfigurationList; 519 | buildConfigurations = ( 520 | E74DE56722333E83008CC5EE /* Debug */, 521 | E74DE56822333E83008CC5EE /* Release */, 522 | ); 523 | defaultConfigurationIsVisible = 0; 524 | defaultConfigurationName = Release; 525 | }; 526 | E74DE56922333E83008CC5EE /* Build configuration list for PBXNativeTarget "CBInjectionTests" */ = { 527 | isa = XCConfigurationList; 528 | buildConfigurations = ( 529 | E74DE56A22333E83008CC5EE /* Debug */, 530 | E74DE56B22333E83008CC5EE /* Release */, 531 | ); 532 | defaultConfigurationIsVisible = 0; 533 | defaultConfigurationName = Release; 534 | }; 535 | /* End XCConfigurationList section */ 536 | }; 537 | rootObject = E74DE54922333E83008CC5EE /* Project object */; 538 | } 539 | --------------------------------------------------------------------------------