├── NeedleDependencies ├── NeedleDependencies │ ├── copyright_header.txt │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── NeedleDependencies.entitlements │ ├── NeedleDependenciesApp.swift │ ├── LogInComponent.swift │ ├── RootComponent.swift │ ├── AuthenticatedComponent.swift │ ├── NeedleGenerated.swift │ └── ContentView.swift └── NeedleDependencies.xcodeproj │ └── project.pbxproj ├── SwiftDependencies ├── SwiftDependencies │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── App.swift │ ├── LoggedOutFeature.swift │ ├── AppFeature.swift │ ├── Dependencies.swift │ └── AuthenticatedFeature.swift └── SwiftDependencies.xcodeproj │ └── project.pbxproj ├── FactoryDependencies ├── FactoryDependencies │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── Info.plist │ ├── Model.swift │ ├── FactoryDependenciesApp.swift │ ├── FactoryDependencies.entitlements │ ├── Container.swift │ └── ContentView.swift └── FactoryDependencies.xcodeproj │ └── project.pbxproj ├── PassedDependencies ├── PassedDependencies │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── Model.swift │ ├── PassedDependenciesApp.swift │ ├── PassedDependencies.entitlements │ ├── Container.swift │ ├── Factories │ │ └── AuthenticatedFactory.swift │ └── ContentView.swift └── PassedDependencies.xcodeproj │ └── project.pbxproj ├── ComposableDependencies ├── ComposableDependencies │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── ComposableDependencies.entitlements │ ├── ComposableDependenciesApp.swift │ ├── ReducerReader │ │ └── ReducerReader.swift │ ├── Dependencies.swift │ ├── ContentView.swift │ └── Features.swift └── ComposableDependencies.xcodeproj │ ├── xcshareddata │ └── xcschemes │ │ └── ComposableDependencies.xcscheme │ └── project.pbxproj ├── images └── injection_frameworks_compared.png ├── EnvironmentDependencies ├── EnvironmentDependencies │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── Model.swift │ ├── EnvironmentDependenciesApp.swift │ ├── EnvironmentDependencies.entitlements │ ├── EnvironmentSetup.swift │ └── ContentView.swift └── EnvironmentDependencies.xcodeproj │ └── project.pbxproj ├── SharedDependencies ├── .gitignore ├── Tests │ └── DependenciesTests │ │ └── DependenciesTests.swift ├── Sources │ └── SharedDependencies │ │ ├── Authentication.swift │ │ ├── UserManager.swift │ │ ├── LogInSwitcher.swift │ │ ├── Placeholders.swift │ │ └── StoryFetcher.swift └── Package.swift ├── DependenciesCompared.xcworkspace ├── xcshareddata │ ├── IDEWorkspaceChecks.plist │ └── swiftpm │ │ └── Package.resolved └── contents.xcworkspacedata ├── .gitignore └── README.md /NeedleDependencies/NeedleDependencies/copyright_header.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /SwiftDependencies/SwiftDependencies/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /FactoryDependencies/FactoryDependencies/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /NeedleDependencies/NeedleDependencies/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PassedDependencies/PassedDependencies/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ComposableDependencies/ComposableDependencies/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /images/injection_frameworks_compared.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LucasVanDongen/SwiftDependencyInjectionCompared/HEAD/images/injection_frameworks_compared.png -------------------------------------------------------------------------------- /EnvironmentDependencies/EnvironmentDependencies/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /NeedleDependencies/NeedleDependencies/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PassedDependencies/PassedDependencies/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftDependencies/SwiftDependencies/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /FactoryDependencies/FactoryDependencies/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ComposableDependencies/ComposableDependencies/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /EnvironmentDependencies/EnvironmentDependencies/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SharedDependencies/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | xcuserdata/ 5 | DerivedData/ 6 | .swiftpm/configuration/registries.json 7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 8 | .netrc 9 | -------------------------------------------------------------------------------- /FactoryDependencies/FactoryDependencies/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /NeedleDependencies/NeedleDependencies/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /PassedDependencies/PassedDependencies/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SwiftDependencies/SwiftDependencies/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /FactoryDependencies/FactoryDependencies/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ComposableDependencies/ComposableDependencies/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /EnvironmentDependencies/EnvironmentDependencies/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /FactoryDependencies/FactoryDependencies/Model.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Model.swift 3 | // PassedDependencies 4 | // 5 | // Created by Lucas van Dongen on 06/03/2024. 6 | // 7 | 8 | import Foundation 9 | 10 | enum AppState { 11 | case loggedOut 12 | case authenticated(token: String) 13 | } 14 | -------------------------------------------------------------------------------- /PassedDependencies/PassedDependencies/Model.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Model.swift 3 | // PassedDependencies 4 | // 5 | // Created by Lucas van Dongen on 06/03/2024. 6 | // 7 | 8 | import Foundation 9 | 10 | enum AppState { 11 | case loggedOut 12 | case authenticated(token: String) 13 | } 14 | -------------------------------------------------------------------------------- /EnvironmentDependencies/EnvironmentDependencies/Model.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Model.swift 3 | // PassedDependencies 4 | // 5 | // Created by Lucas van Dongen on 06/03/2024. 6 | // 7 | 8 | import Foundation 9 | 10 | enum AppState { 11 | case loggedOut 12 | case authenticated(token: String) 13 | } 14 | -------------------------------------------------------------------------------- /SwiftDependencies/SwiftDependencies/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /DependenciesCompared.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /FactoryDependencies/FactoryDependencies/FactoryDependenciesApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FactoryDependenciesApp.swift 3 | // FactoryDependencies 4 | // 5 | // Created by Lucas van Dongen on 12/03/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct FactoryDependenciesApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /FactoryDependencies/FactoryDependencies/FactoryDependencies.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /NeedleDependencies/NeedleDependencies/NeedleDependencies.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /PassedDependencies/PassedDependencies/PassedDependenciesApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PassedDependenciesApp.swift 3 | // PassedDependencies 4 | // 5 | // Created by Lucas van Dongen on 06/03/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @MainActor 11 | @main 12 | struct PassedDependenciesApp: App { 13 | var body: some Scene { 14 | WindowGroup { 15 | ContentView() 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /PassedDependencies/PassedDependencies/PassedDependencies.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /EnvironmentDependencies/EnvironmentDependencies/EnvironmentDependenciesApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EnvironmentDependenciesApp.swift 3 | // EnvironmentDependencies 4 | // 5 | // Created by Lucas van Dongen on 15/03/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct EnvironmentDependenciesApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ComposableDependencies/ComposableDependencies/ComposableDependencies.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /EnvironmentDependencies/EnvironmentDependencies/EnvironmentDependencies.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /NeedleDependencies/NeedleDependencies/NeedleDependenciesApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NeedleDependenciesApp.swift 3 | // NeedleDependencies 4 | // 5 | // Created by Lucas van Dongen on 12/03/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct NeedleDependenciesApp: App { 12 | init() { 13 | registerProviderFactories() 14 | } 15 | 16 | var body: some Scene { 17 | WindowGroup { 18 | ContentView() 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SharedDependencies/Tests/DependenciesTests/DependenciesTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import Dependencies 3 | 4 | final class DependenciesTests: XCTestCase { 5 | func testExample() throws { 6 | // XCTest Documentation 7 | // https://developer.apple.com/documentation/xctest 8 | 9 | // Defining Test Cases and Test Methods 10 | // https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SwiftDependencies/SwiftDependencies/App.swift: -------------------------------------------------------------------------------- 1 | // 2 | // App.swift 3 | // SwiftDependencies 4 | // 5 | // Created by Brandon Williams on 30/03/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @MainActor 11 | @main 12 | struct SwiftDependenciesApp: App { 13 | let model = AppModel( 14 | state: .loggedOut( 15 | LoggedOutModel() 16 | ) 17 | ) 18 | 19 | var body: some Scene { 20 | WindowGroup { 21 | AppView(model: model) 22 | } 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.swp 3 | *~.nib 4 | DerivedData/ 5 | build/ 6 | *.pbxuser 7 | *.mode1v3 8 | *.mode2v3 9 | *.perspectivev3 10 | !default.pbxuser 11 | !default.mode1v3 12 | !default.mode2v3 13 | !default.perspectivev3 14 | xcuserdata 15 | !xcshareddata 16 | !xcschemes 17 | *.moved-aside 18 | /Pods 19 | /Carthage 20 | 21 | .swiftpm 22 | /node_modules 23 | /tmp 24 | 25 | .env 26 | .env.* 27 | 28 | **/fastlane/report.xml 29 | **/fastlane/Preview.html 30 | **/fastlane/screenshots 31 | **/fastlane/test_output 32 | -------------------------------------------------------------------------------- /SharedDependencies/Sources/SharedDependencies/Authentication.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Authentication.swift 3 | // 4 | // 5 | // Created by Lucas van Dongen on 05/03/2024. 6 | // 7 | 8 | import Foundation 9 | 10 | public protocol Authenticating: AnyActor { 11 | func authenticate() async throws -> String 12 | } 13 | 14 | public actor Authentication: Authenticating { 15 | public init() { } 16 | 17 | public func authenticate() async throws -> String { 18 | try await Task.sleep(for: .seconds(2)) 19 | return "V4L1D-T0K3N" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ComposableDependencies/ComposableDependencies/ComposableDependenciesApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ComposableDependenciesApp.swift 3 | // ComposableDependencies 4 | // 5 | // Created by Lucas van Dongen on 04/03/2024. 6 | // 7 | 8 | import ComposableArchitecture 9 | import SwiftUI 10 | 11 | @main 12 | struct ComposableDependenciesApp: App { 13 | @State private var store = Store(initialState: .logIn(.waiting)) { 14 | AppRootFeature.body 15 | } 16 | 17 | var body: some Scene { 18 | WindowGroup { 19 | AppView(store: store) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /SharedDependencies/Sources/SharedDependencies/UserManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserManager.swift 3 | // 4 | // 5 | // Created by Lucas van Dongen on 05/03/2024. 6 | // 7 | 8 | import Foundation 9 | 10 | // ObservableObject is really here for EnvironmentObject 11 | public protocol UserManaging: Sendable { 12 | var token: String { get set } 13 | 14 | func update(user: String) async throws -> Bool 15 | } 16 | 17 | public struct UserManager: UserManaging { 18 | public var token: String 19 | 20 | public init(token: String) { 21 | self.token = token 22 | } 23 | 24 | public func update(user: String) async throws -> Bool { 25 | try await Task.sleep(for: .seconds(2)) 26 | return true 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SharedDependencies/Sources/SharedDependencies/LogInSwitcher.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LogInSwitcher.swift 3 | // 4 | // 5 | // Created by Lucas van Dongen on 12/03/2024. 6 | // 7 | 8 | import AsyncAlgorithms 9 | import Foundation 10 | 11 | public protocol LogInSwitching: Sendable { 12 | var tokenChannel: AsyncChannel { get } 13 | 14 | func loggedIn(with token: String) async 15 | func loggedOut() async 16 | } 17 | 18 | public final class LogInSwitcher: LogInSwitching { 19 | public let tokenChannel = AsyncChannel() 20 | 21 | public init() { } 22 | 23 | public func loggedIn(with token: String) async { 24 | await tokenChannel.send(token) 25 | } 26 | 27 | public func loggedOut() async { 28 | await tokenChannel.send("") 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /NeedleDependencies/NeedleDependencies/LogInComponent.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LogInComponent.swift 3 | // NeedleDependencies 4 | // 5 | // Created by Lucas van Dongen on 12/03/2024. 6 | // 7 | 8 | import NeedleFoundation 9 | import SharedDependencies 10 | import SwiftUI 11 | 12 | protocol LogInDependency: Dependency { 13 | var logInSwitcher: any LogInSwitching { get } 14 | } 15 | 16 | class LogInComponent: Component { 17 | var authentication: Authenticating { 18 | Authentication() 19 | } 20 | 21 | var logInView: some View { 22 | LogInView( 23 | authentication: authentication, 24 | logInSwitcher: dependency.logInSwitcher // This switcher "automagically" appears because of Needle's generated code 25 | ) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SharedDependencies/Sources/SharedDependencies/Placeholders.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Placeholders.swift 3 | // 4 | // 5 | // Created by Lucas van Dongen on 22/03/2024. 6 | // 7 | 8 | import Foundation 9 | 10 | // This implementation is used to prevent a `nil` value for this dependency while the user is not authenticated yet 11 | public struct PlaceholderUserManager: UserManaging { 12 | public var token = "WR0NG_T0K3N" 13 | 14 | public init() { } 15 | 16 | public func update(user: String) async throws -> Bool { 17 | return false 18 | } 19 | } 20 | 21 | public struct PlaceholderStoryFetcher: StoryFetching { 22 | public var token = "WR0NG_T0K3N" 23 | public init() { } 24 | 25 | // You have an issue if this function would actually be called 26 | public func fetchStories() async throws -> [Story] { 27 | return [] 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SharedDependencies/Sources/SharedDependencies/StoryFetcher.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StoryFetcher.swift 3 | // 4 | // 5 | // Created by Lucas van Dongen on 19/03/2024. 6 | // 7 | 8 | import Foundation 9 | 10 | public struct Story: Sendable, Equatable { 11 | public let author: String 12 | public let name: String 13 | } 14 | 15 | public protocol StoryFetching: Sendable, Observable { 16 | var token: String { get set } 17 | func fetchStories() async throws -> [Story] 18 | } 19 | 20 | @Observable 21 | public final class StoryFetcher: StoryFetching { 22 | public var token: String 23 | 24 | public init(token: String) { 25 | self.token = token 26 | } 27 | 28 | public func fetchStories() async throws -> [Story] { 29 | try await Task.sleep(for: .seconds(2)) 30 | return [ 31 | Story(author: "Frank Herbert", name: "Dune"), 32 | Story(author: "Larry Niven", name: "Ringworld"), 33 | Story(author: "Vernor Vinge", name: "A Fire Upon the Deep") 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /DependenciesCompared.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 10 | 12 | 13 | 14 | 16 | 17 | 19 | 20 | 22 | 23 | 25 | 26 | 28 | 29 | 31 | 32 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /ComposableDependencies/ComposableDependencies/ReducerReader/ReducerReader.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReducerReader.swift 3 | // ComposableDependencies 4 | // 5 | // Created by Lucas van Dongen on 13/03/2024. 6 | // 7 | 8 | import ComposableArchitecture 9 | 10 | /// A reducer that builds a reducer from the current state and action. 11 | public struct ReducerReader: Reducer where Reader.State == State, Reader.Action == Action { 12 | @usableFromInline 13 | let reader: (State, Action) -> Reader 14 | 15 | /// Initializes a reducer that builds a reducer from the current state and action. 16 | /// 17 | /// - Parameter reader: A reducer builder that has access to the current state and action. 18 | @inlinable 19 | public init(@ReducerBuilder reader: @escaping (State, Action) -> Reader) { 20 | self.init(internal: reader) 21 | } 22 | 23 | @usableFromInline 24 | init(internal reader: @escaping (State, Action) -> Reader) { 25 | self.reader = reader 26 | } 27 | 28 | @inlinable 29 | public func reduce(into state: inout State, action: Action) -> Effect { 30 | self.reader(state, action).reduce(into: &state, action: action) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /FactoryDependencies/FactoryDependencies/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "scale" : "1x", 6 | "size" : "16x16" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "scale" : "2x", 11 | "size" : "16x16" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "scale" : "1x", 16 | "size" : "32x32" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "scale" : "2x", 21 | "size" : "32x32" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "scale" : "1x", 26 | "size" : "128x128" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "scale" : "2x", 31 | "size" : "128x128" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "scale" : "1x", 36 | "size" : "256x256" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "scale" : "2x", 41 | "size" : "256x256" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "scale" : "1x", 46 | "size" : "512x512" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "scale" : "2x", 51 | "size" : "512x512" 52 | } 53 | ], 54 | "info" : { 55 | "author" : "xcode", 56 | "version" : 1 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /NeedleDependencies/NeedleDependencies/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "scale" : "1x", 6 | "size" : "16x16" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "scale" : "2x", 11 | "size" : "16x16" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "scale" : "1x", 16 | "size" : "32x32" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "scale" : "2x", 21 | "size" : "32x32" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "scale" : "1x", 26 | "size" : "128x128" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "scale" : "2x", 31 | "size" : "128x128" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "scale" : "1x", 36 | "size" : "256x256" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "scale" : "2x", 41 | "size" : "256x256" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "scale" : "1x", 46 | "size" : "512x512" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "scale" : "2x", 51 | "size" : "512x512" 52 | } 53 | ], 54 | "info" : { 55 | "author" : "xcode", 56 | "version" : 1 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /EnvironmentDependencies/EnvironmentDependencies/EnvironmentSetup.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EnvironmentSetup.swift 3 | // EnvironmentDependencies 4 | // 5 | // Created by Lucas van Dongen on 23/03/2024. 6 | // 7 | 8 | import Foundation 9 | import SharedDependencies 10 | import SwiftUI 11 | 12 | private struct AuthenticationEnvironmentKey: EnvironmentKey { 13 | static let defaultValue: Authenticating = Authentication() 14 | } 15 | 16 | private struct UserManagerEnvironmentKey: EnvironmentKey { 17 | static let defaultValue: UserManaging = PlaceholderUserManager() 18 | } 19 | 20 | private struct LogInSwitcherEnvironmentKey: EnvironmentKey { 21 | static let defaultValue: LogInSwitching = LogInSwitcher() 22 | } 23 | 24 | extension EnvironmentValues { 25 | var authentication: Authenticating { 26 | get { self[AuthenticationEnvironmentKey.self] } 27 | set { self[AuthenticationEnvironmentKey.self] = newValue } 28 | } 29 | var userManager: UserManaging { 30 | get { self[UserManagerEnvironmentKey.self] } 31 | set { self[UserManagerEnvironmentKey.self] = newValue } 32 | } 33 | var logInSwitcher: LogInSwitching { 34 | get { self[LogInSwitcherEnvironmentKey.self] } 35 | set { self[LogInSwitcherEnvironmentKey.self] = newValue } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /PassedDependencies/PassedDependencies/Container.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Container.swift 3 | // PassedDependencies 4 | // 5 | // Created by Lucas van Dongen on 06/03/2024. 6 | // 7 | 8 | import Combine 9 | import SharedDependencies 10 | 11 | protocol LogInDependenciesContaining { 12 | var authentication: Authenticating { get } 13 | var logInSwitcher: any LogInSwitching { get } 14 | } 15 | 16 | class LogInDependencies: LogInDependenciesContaining { 17 | let authentication: Authenticating = Authentication() 18 | let logInSwitcher: any LogInSwitching = LogInSwitcher() 19 | } 20 | 21 | protocol AuthenticatedDependenciesContaining { 22 | var logInSwitcher: any LogInSwitching { get } 23 | var userManager: any UserManaging { get } 24 | var storyFetcher: any StoryFetching { get } 25 | } 26 | 27 | class AuthenticatedDependencies: AuthenticatedDependenciesContaining { 28 | let userManager: any UserManaging 29 | let logInSwitcher: any LogInSwitching 30 | let storyFetcher: any StoryFetching 31 | 32 | init( 33 | token: String, 34 | logInSwitcher: any LogInSwitching 35 | ) { 36 | self.userManager = UserManager(token: token) 37 | self.logInSwitcher = logInSwitcher 38 | self.storyFetcher = StoryFetcher(token: token) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /FactoryDependencies/FactoryDependencies/Container.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Container.swift 3 | // PassedDependencies 4 | // 5 | // Created by Lucas van Dongen on 06/03/2024. 6 | // 7 | 8 | import Combine 9 | import Factory 10 | import SharedDependencies 11 | 12 | extension Container { 13 | var authentication: Factory { 14 | self { Authentication() }.singleton 15 | } 16 | 17 | var logInSwitcher: Factory { 18 | self { LogInSwitcher() }.singleton 19 | } 20 | 21 | var userManager: Factory { 22 | self { PlaceholderUserManager() }.graph 23 | } 24 | 25 | var storyFetcher: Factory { 26 | self { PlaceholderStoryFetcher() }.graph 27 | } 28 | } 29 | 30 | class AuthenticatedDependenciesManager { 31 | static func handle(token: String) { 32 | switch token.isEmpty { 33 | case true: break // We're relying on the `graph` feature to dismiss `token`-based real implementations 34 | case false: register(with: token) 35 | } 36 | } 37 | 38 | static func register(with token: String) { 39 | Container.shared.userManager.register { UserManager(token: token) } 40 | Container.shared.storyFetcher.register { StoryFetcher(token: token) } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /PassedDependencies/PassedDependencies/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "scale" : "1x", 11 | "size" : "16x16" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "scale" : "2x", 16 | "size" : "16x16" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "scale" : "1x", 21 | "size" : "32x32" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "scale" : "2x", 26 | "size" : "32x32" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "scale" : "1x", 31 | "size" : "128x128" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "scale" : "2x", 36 | "size" : "128x128" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "scale" : "1x", 41 | "size" : "256x256" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "scale" : "2x", 46 | "size" : "256x256" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "scale" : "1x", 51 | "size" : "512x512" 52 | }, 53 | { 54 | "idiom" : "mac", 55 | "scale" : "2x", 56 | "size" : "512x512" 57 | } 58 | ], 59 | "info" : { 60 | "author" : "xcode", 61 | "version" : 1 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /NeedleDependencies/NeedleDependencies/RootComponent.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RootComponent.swift 3 | // NeedleDependencies 4 | // 5 | // Created by Lucas van Dongen on 12/03/2024. 6 | // 7 | 8 | import SharedDependencies 9 | import NeedleFoundation 10 | import SwiftUI 11 | 12 | class RootComponent: BootstrapComponent { 13 | var logInComponent: LogInComponent { LogInComponent(parent: self) } 14 | 15 | func authenticatedComponent(token: String) -> AuthenticatedComponent { 16 | AuthenticatedComponent( 17 | parent: self, 18 | token: token 19 | ) 20 | } 21 | } 22 | 23 | extension RootComponent: LogInDependency { 24 | var logInSwitcher: any LogInSwitching { 25 | shared { LogInSwitcher() } 26 | } 27 | } 28 | 29 | protocol AppViewBuilding { 30 | @MainActor 31 | var appView: AppView { get } 32 | 33 | @MainActor 34 | var appViewModel: AppViewModel { get } 35 | } 36 | 37 | extension RootComponent: AppViewBuilding { 38 | @MainActor 39 | var appView: AppView { 40 | AppView( 41 | viewModel: self.appViewModel, 42 | rootComponent: self, 43 | logInComponent: logInComponent 44 | ) 45 | } 46 | 47 | @MainActor 48 | var appViewModel: AppViewModel { 49 | AppViewModel(logInSwitcher: logInComponent.logInSwitcher) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ComposableDependencies/ComposableDependencies/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "scale" : "1x", 11 | "size" : "16x16" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "scale" : "2x", 16 | "size" : "16x16" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "scale" : "1x", 21 | "size" : "32x32" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "scale" : "2x", 26 | "size" : "32x32" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "scale" : "1x", 31 | "size" : "128x128" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "scale" : "2x", 36 | "size" : "128x128" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "scale" : "1x", 41 | "size" : "256x256" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "scale" : "2x", 46 | "size" : "256x256" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "scale" : "1x", 51 | "size" : "512x512" 52 | }, 53 | { 54 | "idiom" : "mac", 55 | "scale" : "2x", 56 | "size" : "512x512" 57 | } 58 | ], 59 | "info" : { 60 | "author" : "xcode", 61 | "version" : 1 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /EnvironmentDependencies/EnvironmentDependencies/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "scale" : "1x", 11 | "size" : "16x16" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "scale" : "2x", 16 | "size" : "16x16" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "scale" : "1x", 21 | "size" : "32x32" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "scale" : "2x", 26 | "size" : "32x32" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "scale" : "1x", 31 | "size" : "128x128" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "scale" : "2x", 36 | "size" : "128x128" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "scale" : "1x", 41 | "size" : "256x256" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "scale" : "2x", 46 | "size" : "256x256" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "scale" : "1x", 51 | "size" : "512x512" 52 | }, 53 | { 54 | "idiom" : "mac", 55 | "scale" : "2x", 56 | "size" : "512x512" 57 | } 58 | ], 59 | "info" : { 60 | "author" : "xcode", 61 | "version" : 1 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /SwiftDependencies/SwiftDependencies/LoggedOutFeature.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LoggedOutFeature.swift 3 | // SwiftDependencies 4 | // 5 | // Created by Brandon Williams on 30/03/2024. 6 | // 7 | 8 | import Dependencies 9 | import SwiftUI 10 | 11 | @MainActor 12 | @Observable 13 | class LoggedOutModel { 14 | @ObservationIgnored 15 | @Dependency(\.authentication) var authentication 16 | @ObservationIgnored 17 | @Dependency(\.logInSwitcher) var logInSwitcher 18 | 19 | var isAuthenticating = false 20 | func loginButtonTapped() async { 21 | isAuthenticating = true 22 | defer { isAuthenticating = false } 23 | do { 24 | let token = try await authentication.authenticate() 25 | await logInSwitcher.loggedIn(with: token) 26 | } catch { 27 | // TODO: Handle this 28 | } 29 | } 30 | } 31 | 32 | struct LoggedOutView: View { 33 | let model: LoggedOutModel 34 | 35 | var body: some View { 36 | VStack { 37 | if model.isAuthenticating { 38 | HStack { 39 | Text("Authenticating...") 40 | ProgressView() 41 | } 42 | } else { 43 | Text("You are logged out") 44 | } 45 | Button("Log in") { 46 | Task { await model.loginButtonTapped() } 47 | } 48 | .disabled(model.isAuthenticating) 49 | } 50 | } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /SharedDependencies/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.9 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let name = "SharedDependencies" 7 | let asyncAlgorithms: Target.Dependency = .product(name: "AsyncAlgorithms", package: "swift-async-algorithms") 8 | let strictConcurrency: SwiftSetting = .enableExperimentalFeature("StrictConcurrency") 9 | 10 | let package = Package( 11 | name: name, 12 | platforms: [ 13 | .macOS(.v14), 14 | .iOS(.v17), 15 | .visionOS(.v1), 16 | .tvOS(.v15), 17 | .watchOS(.v10) 18 | ], 19 | products: [ 20 | .library( 21 | name: name, 22 | targets: [name] 23 | ) 24 | ], 25 | dependencies: [ 26 | // .package(url: "git@github.com:apple/swift-async-algorithms", from: "1.0.0")//, 27 | .package(url: "https://github.com/apple/swift-async-algorithms", from: "1.0.0") 28 | ], 29 | targets: [ 30 | .target( 31 | name: name, 32 | dependencies: [ 33 | asyncAlgorithms 34 | ], 35 | swiftSettings: [ 36 | strictConcurrency 37 | ] 38 | ), 39 | .testTarget( 40 | name: "DependenciesTests", 41 | dependencies: [ 42 | "SharedDependencies" 43 | ], 44 | swiftSettings: [ 45 | strictConcurrency 46 | ] 47 | ), 48 | ] 49 | ) 50 | -------------------------------------------------------------------------------- /SwiftDependencies/SwiftDependencies/AppFeature.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppFeature.swift 3 | // SwiftDependencies 4 | // 5 | // Created by Brandon Williams on 30/03/2024. 6 | // 7 | 8 | import Dependencies 9 | import SharedDependencies 10 | import SwiftUI 11 | 12 | @MainActor 13 | @Observable 14 | class AppModel { 15 | @ObservationIgnored 16 | @Dependency(\.logInSwitcher) var logInSwitcher 17 | 18 | private(set) var state: State 19 | 20 | init(state: State) { 21 | self.state = state 22 | self.subscribe() 23 | } 24 | 25 | enum State { 26 | case authenticated(AuthenticatedModel) 27 | case loggedOut(LoggedOutModel) 28 | } 29 | 30 | func subscribe() { 31 | Task { 32 | for await token in logInSwitcher.tokenChannel { 33 | if token.isEmpty { 34 | state = .loggedOut(LoggedOutModel()) 35 | } else { 36 | // Providing the 'token' to AuthenticatedModel is now proof that the user is 37 | // authenticated. 38 | state = .authenticated(AuthenticatedModel(token: token)) 39 | } 40 | } 41 | } 42 | } 43 | } 44 | 45 | struct AppView: View { 46 | let model: AppModel 47 | 48 | var body: some View { 49 | switch model.state { 50 | case let .authenticated(model): 51 | AuthenticatedView(model: model) 52 | case let .loggedOut(model): 53 | LoggedOutView(model: model) 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /NeedleDependencies/NeedleDependencies/AuthenticatedComponent.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AuthenticatedComponent.swift 3 | // NeedleDependencies 4 | // 5 | // Created by Lucas van Dongen on 12/03/2024. 6 | // 7 | 8 | import NeedleFoundation 9 | import SharedDependencies 10 | import SwiftUI 11 | 12 | protocol AuthenticatedDependency: Dependency { 13 | var logInSwitcher: any LogInSwitching { get } 14 | } 15 | 16 | class AuthenticatedComponent: Component { 17 | var userManager: any UserManaging { 18 | return shared { UserManager(token: token) } 19 | } 20 | 21 | var storyFetcher: any StoryFetching { 22 | return shared { StoryFetcher(token: token) } 23 | } 24 | 25 | private let token: String 26 | 27 | init( 28 | parent: Scope, 29 | token: String 30 | ) { 31 | self.token = token 32 | super.init(parent: parent) 33 | } 34 | } 35 | 36 | @MainActor 37 | protocol AuthenticatedViewBuilding { 38 | var authenticatedView: AuthenticatedView { get } 39 | var storiesView: StoriesView { get } 40 | var userManagementView: UserManagementView { get } 41 | } 42 | 43 | extension AuthenticatedComponent: AuthenticatedViewBuilding { 44 | var authenticatedView: AuthenticatedView { 45 | AuthenticatedView( 46 | logInSwitcher: dependency.logInSwitcher, 47 | component: self 48 | ) 49 | } 50 | 51 | var storiesView: StoriesView { 52 | StoriesView(storyFetcher: storyFetcher) 53 | } 54 | 55 | var userManagementView: UserManagementView { 56 | UserManagementView(userManager: userManager) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /ComposableDependencies/ComposableDependencies/Dependencies.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Dependencies.swift 3 | // ComposableDependencies 4 | // 5 | // Created by Lucas van Dongen on 05/03/2024. 6 | // 7 | 8 | import ComposableArchitecture 9 | import SharedDependencies 10 | 11 | private enum AuthenticationKey: DependencyKey { 12 | static let liveValue: Authenticating = Authentication() 13 | } 14 | 15 | extension DependencyValues { 16 | var authentication: Authenticating { 17 | get { self[AuthenticationKey.self] } 18 | set { self[AuthenticationKey.self] = newValue } 19 | } 20 | } 21 | 22 | // This implementation is used to prevent a `nil` value for this dependency while the user is not authenticated yet 23 | final class PlaceholderUserManager: UserManaging { 24 | var token = "WR0NG_T4K3N" 25 | 26 | func update(user: String) async throws -> Bool { 27 | return false 28 | } 29 | } 30 | 31 | private enum UserManagerKey: DependencyKey { 32 | static let liveValue: any UserManaging = PlaceholderUserManager() 33 | } 34 | 35 | extension DependencyValues { 36 | var userManager: any UserManaging { 37 | get { self[UserManagerKey.self] } 38 | set { self[UserManagerKey.self] = newValue } 39 | } 40 | } 41 | 42 | final class PlaceholderStoryFetcher: StoryFetching { 43 | var token: String = "" 44 | 45 | // If this function would ever be executed, we have a problem 46 | func fetchStories() async throws -> [Story] { 47 | return [] 48 | } 49 | } 50 | 51 | private enum StoryFetcherKey: DependencyKey { 52 | static let liveValue: any StoryFetching = PlaceholderStoryFetcher() 53 | } 54 | 55 | extension DependencyValues { 56 | var storyFetcher: any StoryFetching { 57 | get { self[StoryFetcherKey.self] } 58 | set { self[StoryFetcherKey.self] = newValue } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /SwiftDependencies/SwiftDependencies/Dependencies.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Dependencies.swift 3 | // SwiftDependencies 4 | // 5 | // Created by Brandon Williams on 30/03/2024. 6 | // 7 | 8 | import Dependencies 9 | import SharedDependencies 10 | 11 | private enum LogInSwitchingKey: DependencyKey { 12 | static let liveValue: any LogInSwitching = LogInSwitcher() 13 | } 14 | 15 | extension DependencyValues { 16 | var logInSwitcher: any LogInSwitching { 17 | get { self[LogInSwitchingKey.self] } 18 | set { self[LogInSwitchingKey.self] = newValue } 19 | } 20 | } 21 | 22 | private enum AuthenticationKey: DependencyKey { 23 | static let liveValue: any Authenticating = Authentication() 24 | } 25 | 26 | extension DependencyValues { 27 | var authentication: Authenticating { 28 | get { self[AuthenticationKey.self] } 29 | set { self[AuthenticationKey.self] = newValue } 30 | } 31 | } 32 | 33 | extension DependencyValues { 34 | private enum UserManagerKey: DependencyKey { 35 | static let liveValue: any UserManaging = UserManager(token: "invalid-token") 36 | } 37 | subscript(userManagerForToken token: String) -> any UserManaging { 38 | get { 39 | var manager = self[UserManagerKey.self] 40 | manager.token = token 41 | return manager 42 | } 43 | set { 44 | var newValue = newValue 45 | newValue.token = token 46 | self[UserManagerKey.self] = newValue 47 | } 48 | } 49 | } 50 | 51 | extension DependencyValues { 52 | private enum StoryFetcherKey: DependencyKey { 53 | static let liveValue: any StoryFetching = StoryFetcher(token: "invalid-token") 54 | } 55 | subscript(storyFetcherForToken token: String) -> any StoryFetching { 56 | get { 57 | var manager = self[StoryFetcherKey.self] 58 | manager.token = token 59 | return manager 60 | } 61 | set { 62 | var newValue = newValue 63 | newValue.token = token 64 | self[StoryFetcherKey.self] = newValue 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dependency Injection for Modern Swift Applications 2 | ## Dependency Injection for Modern Swift Applications and Comparing five different approaches towards Dependency Injection 3 | 4 | ![An AI generated hero image showing four syringes stuck into an apple, symbolifying the act of injecting dependencies on Apple platforms](images/injection_frameworks_compared.png) 5 | 6 | This repo belongs to two articles I've written about dependency injection. I'm reviewing the following five principeles: 7 | 8 | * [Compile-Time Safety](https://dependency_injection_swift_swiftui.php#compile-time-safety) - if it compiles, is it correct and crash-free? 9 | * [Generational Safety](https://dependency_injection_swift_swiftui.php#generational-safety) - can we safely unlock dependencies later on? 10 | * [Scalability](https://dependency_injection_swift_swiftui.php#scaling) - how hard is it to maintain or add features when the app grows? 11 | * [Usability](https://dependency_injection_swift_swiftui.php#usability) - how easy is it to new team members and to add or maintain features? 12 | * [Testability](https://dependency_injection_swift_swiftui.php#testability-and-previews) - can we easily mock our dependencies for tests and previews? 13 | 14 | This repo holds simple but complete examples that highlight the different aspects of DI for each different approach. The following five frameworks or techniques for DI have been selected to give a complete overview of all different types of solutions that exist: 15 | 16 | * [Manual Tree](https://github.com/LucasVanDongen/SwiftDependencyInjectionCompared/tree/main/PassedDependencies) - Pass all dependencies manually 17 | * [EnvironmentObject](https://github.com/LucasVanDongen/SwiftDependencyInjectionCompared/tree/main/EnvironmentDependencies) - Using SwiftUI's built in storage 18 | * [Factory](https://github.com/LucasVanDongen/SwiftDependencyInjectionCompared/tree/main/FactoryDependencies) - A simple statically declared container approach 19 | * [Needle](https://github.com/LucasVanDongen/SwiftDependencyInjectionCompared/tree/main/NeedleDependencies) - Uber's solution to boilerplate-heavy manual solutions 20 | * [Composable Architecture](https://https://github.com/LucasVanDongen/SwiftDependencyInjectionCompared/tree/main/ComposableDependencies) - How does TCA's solution compare? 21 | 22 | Read the first article ["Managing Dependencies in the Age of SwiftUI" here](dependency_injection_swift_swiftui.php), and the second article ["Comparing five different approaches towards Dependency Injection" here](dependency_injection_swift_swiftui.php). 23 | -------------------------------------------------------------------------------- /PassedDependencies/PassedDependencies/Factories/AuthenticatedFactory.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AuthenticatedFactory.swift 3 | // PassedDependencies 4 | // 5 | // Created by Lucas van Dongen on 23/03/2024. 6 | // 7 | 8 | import Foundation 9 | import SharedDependencies 10 | 11 | class AuthenticatedFactory: AuthenticatedDependenciesContaining { 12 | let logInSwitcher: LogInSwitching 13 | let userManager: UserManaging 14 | let storyFetcher: StoryFetching 15 | 16 | /// Everything that is needed to build this Factory needs to be passed forward, including dependencies already created in a parent node 17 | /// - Parameters: 18 | /// - token: The key to unlock the `UserManager` and `StoryFetcher` implementations 19 | /// - logInSwitcher: A dependency we need to pass forward from the root 20 | init( 21 | token: String, 22 | logInSwitcher: LogInSwitching // In Needle, all dependencies inherited from all nodes toward and including the root are handled by the `parent` Component 23 | ) { 24 | self.logInSwitcher = logInSwitcher 25 | userManager = UserManager(token: token) 26 | storyFetcher = StoryFetcher(token: token) 27 | } 28 | } 29 | 30 | // A separate extension for building the Views 31 | // Ideal for keeping your Factories UI dependency free, or for supporting multiple platforms 32 | extension AuthenticatedFactory { 33 | var userManagementView: UserManagementView { 34 | UserManagementView(userManager: userManager) 35 | } 36 | 37 | var storiesView: StoriesView { 38 | StoriesView(storyFetcher: storyFetcher) 39 | } 40 | } 41 | 42 | // Example implementation for AuthenticatedView using this Factory: 43 | import SwiftUI 44 | 45 | @MainActor 46 | struct AuthenticatedFactoryView: View { 47 | let factory: AuthenticatedFactory 48 | 49 | @State private var isLoggingOut = false 50 | 51 | var body: some View { 52 | VStack { 53 | // This View now knows nothing about how these Views are built 54 | factory.userManagementView 55 | factory.storiesView 56 | Button { 57 | isLoggingOut = true 58 | } label: { 59 | Text("Log Out") 60 | }.task(id: isLoggingOut, priority: .high) { 61 | guard isLoggingOut else { 62 | return 63 | } 64 | 65 | defer { 66 | isLoggingOut = false 67 | } 68 | 69 | await factory.logInSwitcher.loggedOut() 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /NeedleDependencies/NeedleDependencies/NeedleGenerated.swift: -------------------------------------------------------------------------------- 1 | 2 | 3 | import NeedleFoundation 4 | import SharedDependencies 5 | import SwiftUI 6 | 7 | // swiftlint:disable unused_declaration 8 | private let needleDependenciesHash : String? = nil 9 | 10 | // MARK: - Traversal Helpers 11 | 12 | private func parent1(_ component: NeedleFoundation.Scope) -> NeedleFoundation.Scope { 13 | return component.parent 14 | } 15 | 16 | // MARK: - Providers 17 | 18 | #if !NEEDLE_DYNAMIC 19 | 20 | private class AuthenticatedDependencycda53ef9a0d1fafe1614Provider: AuthenticatedDependency { 21 | var logInSwitcher: any LogInSwitching { 22 | return rootComponent.logInSwitcher 23 | } 24 | private let rootComponent: RootComponent 25 | init(rootComponent: RootComponent) { 26 | self.rootComponent = rootComponent 27 | } 28 | } 29 | /// ^->RootComponent->AuthenticatedComponent 30 | private func factory31f7272d9f1e1bb4556eb3a8f24c1d289f2c0f2e(_ component: NeedleFoundation.Scope) -> AnyObject { 31 | return AuthenticatedDependencycda53ef9a0d1fafe1614Provider(rootComponent: parent1(component) as! RootComponent) 32 | } 33 | private class LogInDependency59c56af202a7286b1d4fProvider: LogInDependency { 34 | var logInSwitcher: any LogInSwitching { 35 | return rootComponent.logInSwitcher 36 | } 37 | private let rootComponent: RootComponent 38 | init(rootComponent: RootComponent) { 39 | self.rootComponent = rootComponent 40 | } 41 | } 42 | /// ^->RootComponent->LogInComponent 43 | private func factory722f9ff168b373921da5b3a8f24c1d289f2c0f2e(_ component: NeedleFoundation.Scope) -> AnyObject { 44 | return LogInDependency59c56af202a7286b1d4fProvider(rootComponent: parent1(component) as! RootComponent) 45 | } 46 | 47 | #else 48 | extension AuthenticatedComponent: Registration { 49 | public func registerItems() { 50 | keyPathToName[\AuthenticatedDependency.logInSwitcher] = "logInSwitcher-any LogInSwitching" 51 | } 52 | } 53 | extension RootComponent: Registration { 54 | public func registerItems() { 55 | 56 | 57 | } 58 | } 59 | extension LogInComponent: Registration { 60 | public func registerItems() { 61 | keyPathToName[\LogInDependency.logInSwitcher] = "logInSwitcher-any LogInSwitching" 62 | } 63 | } 64 | 65 | 66 | #endif 67 | 68 | private func factoryEmptyDependencyProvider(_ component: NeedleFoundation.Scope) -> AnyObject { 69 | return EmptyDependencyProvider(component: component) 70 | } 71 | 72 | // MARK: - Registration 73 | private func registerProviderFactory(_ componentPath: String, _ factory: @escaping (NeedleFoundation.Scope) -> AnyObject) { 74 | __DependencyProviderRegistry.instance.registerDependencyProviderFactory(for: componentPath, factory) 75 | } 76 | 77 | #if !NEEDLE_DYNAMIC 78 | 79 | @inline(never) private func register1() { 80 | registerProviderFactory("^->RootComponent->AuthenticatedComponent", factory31f7272d9f1e1bb4556eb3a8f24c1d289f2c0f2e) 81 | registerProviderFactory("^->RootComponent", factoryEmptyDependencyProvider) 82 | registerProviderFactory("^->RootComponent->LogInComponent", factory722f9ff168b373921da5b3a8f24c1d289f2c0f2e) 83 | } 84 | #endif 85 | 86 | public func registerProviderFactories() { 87 | #if !NEEDLE_DYNAMIC 88 | register1() 89 | #endif 90 | } 91 | -------------------------------------------------------------------------------- /ComposableDependencies/ComposableDependencies.xcodeproj/xcshareddata/xcschemes/ComposableDependencies.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 10 | 16 | 22 | 23 | 24 | 25 | 26 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /ComposableDependencies/ComposableDependencies/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // ComposableDependencies 4 | // 5 | // Created by Lucas van Dongen on 04/03/2024. 6 | // 7 | 8 | import ComposableArchitecture 9 | import SharedDependencies 10 | import SwiftUI 11 | 12 | @MainActor 13 | struct AuthenticatedView: View { 14 | let store: StoreOf 15 | 16 | let userManagementFeature = Store(initialState: UserManagementFeature.State.loaded) { 17 | UserManagementFeature() 18 | } 19 | let storiesFeature = Store(initialState: StoriesFeature.State.loading) { 20 | StoriesFeature() 21 | } 22 | 23 | var body: some View { 24 | VStack { 25 | UserManagementView(store: userManagementFeature) 26 | StoriesView(store: storiesFeature) 27 | Button { 28 | store.send(.logOut) 29 | } label: { 30 | Text("Log Out") 31 | } 32 | } 33 | } 34 | } 35 | 36 | @MainActor 37 | struct UserManagementView: View { 38 | let store: StoreOf 39 | 40 | @Dependency(\.userManager) var userManager 41 | 42 | var body: some View { 43 | VStack { 44 | Text("You are logged in with token \(userManager.token)") 45 | 46 | switch store.state { 47 | case .loaded: 48 | Button { 49 | store.send(.update) 50 | } label: { 51 | Text("Update User") 52 | } 53 | case .updating: 54 | HStack { 55 | Text("Updating User...") 56 | ProgressView() 57 | } 58 | case let .failed(reason): 59 | Text("Failed updating User:\n\(reason)") 60 | case .updated: 61 | Text("You have updated your user successfully") 62 | } 63 | } 64 | } 65 | } 66 | 67 | @MainActor 68 | struct StoriesView: View { 69 | let store: StoreOf 70 | 71 | var body: some View { 72 | switch store.state { 73 | case .loading: 74 | HStack { 75 | Text("Fetching stories...") 76 | ProgressView() 77 | } 78 | .task { 79 | store.send(.startLoading) 80 | } 81 | case let .failed(reason): 82 | Text("Failed fetching stories:\n\(reason)") 83 | case let .loaded(stories): 84 | List { 85 | ForEach(stories, id: \.name) { story in 86 | Text("Author: \(story.author)\nName: \(story.name)") 87 | } 88 | } 89 | } 90 | } 91 | } 92 | 93 | @MainActor 94 | struct LogInView: View { 95 | let store: StoreOf 96 | 97 | var body: some View { 98 | switch store.state { 99 | case .authenticating: 100 | HStack { 101 | Text("Authenticating...") 102 | ProgressView() 103 | } 104 | case .waiting: 105 | VStack { 106 | Text("You are logged out now") 107 | Button { 108 | store.send(.logIn) 109 | } label: { 110 | Text("Log In") 111 | } 112 | } 113 | } 114 | } 115 | } 116 | 117 | @MainActor 118 | struct AppView: View { 119 | let store: StoreOf 120 | 121 | var body: some View { 122 | switch store.case { 123 | case let .authenticated(store): 124 | AuthenticatedView(store: store) 125 | case let .logIn(store): 126 | LogInView(store: store) 127 | } 128 | } 129 | } 130 | 131 | @MainActor 132 | struct ContentView: View { 133 | let store: StoreOf 134 | 135 | init() { 136 | let authState = LogInFeature.State.waiting 137 | let featureState = AppRootFeature.State.logIn(authState) 138 | 139 | store = Store(initialState: featureState) { 140 | AppRootFeature.body._printChanges() 141 | } 142 | } 143 | 144 | var body: some View { 145 | AppView(store: store) 146 | } 147 | } 148 | 149 | #Preview { 150 | ContentView() 151 | } 152 | -------------------------------------------------------------------------------- /SwiftDependencies/SwiftDependencies/AuthenticatedFeature.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AuthenticatedFeature.swift 3 | // SwiftDependencies 4 | // 5 | // Created by Brandon Williams on 30/03/2024. 6 | // 7 | 8 | import Dependencies 9 | import SharedDependencies 10 | import SwiftUI 11 | 12 | @MainActor 13 | @Observable 14 | class AuthenticatedModel { 15 | @ObservationIgnored 16 | @Dependency(\.logInSwitcher) var logInSwitcher 17 | 18 | var isLoggingOut = false 19 | let stories: StoriesModel 20 | let userManagement: UserManagementModel 21 | 22 | init(token: String) { 23 | stories = StoriesModel(token: token) 24 | userManagement = UserManagementModel(token: token) 25 | } 26 | 27 | func logoutButtonTapped() async { 28 | isLoggingOut = true 29 | defer { isLoggingOut = false } 30 | 31 | await logInSwitcher.loggedOut() 32 | } 33 | } 34 | 35 | struct AuthenticatedView: View { 36 | let model: AuthenticatedModel 37 | 38 | var body: some View { 39 | Form { 40 | UserManagementView(model: model.userManagement) 41 | StoriesView(model: model.stories) 42 | 43 | Button("Log out") { 44 | Task { await model.logoutButtonTapped() } 45 | } 46 | .disabled(model.isLoggingOut) 47 | } 48 | } 49 | } 50 | 51 | @MainActor 52 | @Observable 53 | class UserManagementModel { 54 | @ObservationIgnored 55 | @Dependency var userManager: any UserManaging 56 | 57 | init(token: String) { 58 | // In order to access the 'userManager` dependency we must supply proof that the user is 59 | // authenticated by passing the token to the subscript key path. 60 | self._userManager = Dependency(\.[userManagerForToken: token]) 61 | self.state = .loaded 62 | } 63 | 64 | var state = State.loaded 65 | 66 | enum State { 67 | case loaded 68 | case updating 69 | case failed(reason: String) 70 | case updated 71 | } 72 | 73 | func updateUserButtonTapped() async { 74 | state = .updating 75 | do { 76 | _ = try await userManager.update(user: "") 77 | state = .updated 78 | } catch { 79 | state = .failed(reason: "Something went wrong") 80 | } 81 | } 82 | } 83 | 84 | struct UserManagementView: View { 85 | let model: UserManagementModel 86 | 87 | var body: some View { 88 | Section { 89 | Text("You are logged in with token \(model.userManager.token)") 90 | switch model.state { 91 | case .loaded: 92 | Button("Update user") { 93 | Task { await model.updateUserButtonTapped() } 94 | } 95 | case .updating: 96 | HStack { Text("Updating User..."); ProgressView() } 97 | case let .failed(reason): 98 | Text("Failed updating User:\n\(reason)") 99 | case .updated: 100 | Text("You have updated your user successfully") 101 | } 102 | } header: { 103 | Text("User management") 104 | } 105 | } 106 | } 107 | 108 | @MainActor 109 | @Observable 110 | class StoriesModel { 111 | @ObservationIgnored 112 | @Dependency private var storyFetcher: any StoryFetching 113 | 114 | init(token: String) { 115 | // In order to access the 'storyFetcher` dependency we must supply proof that the user is 116 | // authenticated by passing the token to the subscript key path. 117 | self._storyFetcher = Dependency(\.[storyFetcherForToken: token]) 118 | self.state = state 119 | } 120 | 121 | var state = State.fetching 122 | 123 | enum State { 124 | case fetching 125 | case failed(reason: String) 126 | case fetched(stories: [Story]) 127 | } 128 | 129 | func onFetch() async { 130 | state = .fetching 131 | do { 132 | state = .fetched(stories: try await storyFetcher.fetchStories()) 133 | } catch let error { 134 | state = .failed(reason: error.localizedDescription) 135 | } 136 | } 137 | } 138 | 139 | struct StoriesView: View { 140 | let model: StoriesModel 141 | 142 | var body: some View { 143 | switch model.state { 144 | case .fetching: 145 | HStack { 146 | Text("Fetching stories...") 147 | ProgressView() 148 | } 149 | .task { await model.onFetch() } 150 | case let .failed(reason): 151 | Text("Failed fetching stories:\n\(reason)") 152 | case let .fetched(stories): 153 | List { 154 | ForEach(stories, id: \.name) { story in 155 | Text("Author: \(story.author)\nName: \(story.name)") 156 | } 157 | } 158 | } 159 | } 160 | } 161 | 162 | -------------------------------------------------------------------------------- /DependenciesCompared.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "pins" : [ 3 | { 4 | "identity" : "combine-schedulers", 5 | "kind" : "remoteSourceControl", 6 | "location" : "https://github.com/pointfreeco/combine-schedulers", 7 | "state" : { 8 | "revision" : "9dc9cbe4bc45c65164fa653a563d8d8db61b09bb", 9 | "version" : "1.0.0" 10 | } 11 | }, 12 | { 13 | "identity" : "factory", 14 | "kind" : "remoteSourceControl", 15 | "location" : "http://github.com/hmlongco/Factory", 16 | "state" : { 17 | "revision" : "587995f7d5cc667951d635fbf6b4252324ba0439", 18 | "version" : "2.3.2" 19 | } 20 | }, 21 | { 22 | "identity" : "needle", 23 | "kind" : "remoteSourceControl", 24 | "location" : "https://github.com/uber/needle", 25 | "state" : { 26 | "branch" : "master", 27 | "revision" : "6db73ae873952794b94fd6bb5111554e23c160af" 28 | } 29 | }, 30 | { 31 | "identity" : "swift-async-algorithms", 32 | "kind" : "remoteSourceControl", 33 | "location" : "https://github.com/apple/swift-async-algorithms", 34 | "state" : { 35 | "revision" : "da4e36f86544cdf733a40d59b3a2267e3a7bbf36", 36 | "version" : "1.0.0" 37 | } 38 | }, 39 | { 40 | "identity" : "swift-case-paths", 41 | "kind" : "remoteSourceControl", 42 | "location" : "https://github.com/pointfreeco/swift-case-paths", 43 | "state" : { 44 | "revision" : "e593aba2c6222daad7c4f2732a431eed2c09bb07", 45 | "version" : "1.3.0" 46 | } 47 | }, 48 | { 49 | "identity" : "swift-clocks", 50 | "kind" : "remoteSourceControl", 51 | "location" : "https://github.com/pointfreeco/swift-clocks", 52 | "state" : { 53 | "revision" : "a8421d68068d8f45fbceb418fbf22c5dad4afd33", 54 | "version" : "1.0.2" 55 | } 56 | }, 57 | { 58 | "identity" : "swift-collections", 59 | "kind" : "remoteSourceControl", 60 | "location" : "https://github.com/apple/swift-collections", 61 | "state" : { 62 | "revision" : "94cf62b3ba8d4bed62680a282d4c25f9c63c2efb", 63 | "version" : "1.1.0" 64 | } 65 | }, 66 | { 67 | "identity" : "swift-composable-architecture", 68 | "kind" : "remoteSourceControl", 69 | "location" : "https://github.com/pointfreeco/swift-composable-architecture", 70 | "state" : { 71 | "revision" : "115fe5af41d333b6156d4924d7c7058bc77fd580", 72 | "version" : "1.9.2" 73 | } 74 | }, 75 | { 76 | "identity" : "swift-concurrency-extras", 77 | "kind" : "remoteSourceControl", 78 | "location" : "https://github.com/pointfreeco/swift-concurrency-extras", 79 | "state" : { 80 | "revision" : "bb5059bde9022d69ac516803f4f227d8ac967f71", 81 | "version" : "1.1.0" 82 | } 83 | }, 84 | { 85 | "identity" : "swift-custom-dump", 86 | "kind" : "remoteSourceControl", 87 | "location" : "https://github.com/pointfreeco/swift-custom-dump", 88 | "state" : { 89 | "revision" : "3ce83179e5f0c83ad54c305779c6b438e82aaf1d", 90 | "version" : "1.2.1" 91 | } 92 | }, 93 | { 94 | "identity" : "swift-dependencies", 95 | "kind" : "remoteSourceControl", 96 | "location" : "https://github.com/pointfreeco/swift-dependencies", 97 | "state" : { 98 | "revision" : "d3a5af3038a09add4d7682f66555d6212058a3c0", 99 | "version" : "1.2.2" 100 | } 101 | }, 102 | { 103 | "identity" : "swift-identified-collections", 104 | "kind" : "remoteSourceControl", 105 | "location" : "https://github.com/pointfreeco/swift-identified-collections", 106 | "state" : { 107 | "revision" : "d1e45f3e1eee2c9193f5369fa9d70a6ddad635e8", 108 | "version" : "1.0.0" 109 | } 110 | }, 111 | { 112 | "identity" : "swift-perception", 113 | "kind" : "remoteSourceControl", 114 | "location" : "https://github.com/pointfreeco/swift-perception", 115 | "state" : { 116 | "revision" : "42240120b2a8797595433288ab4118f8042214c3", 117 | "version" : "1.1.1" 118 | } 119 | }, 120 | { 121 | "identity" : "swift-syntax", 122 | "kind" : "remoteSourceControl", 123 | "location" : "https://github.com/apple/swift-syntax", 124 | "state" : { 125 | "revision" : "64889f0c732f210a935a0ad7cda38f77f876262d", 126 | "version" : "509.1.1" 127 | } 128 | }, 129 | { 130 | "identity" : "swiftui-navigation", 131 | "kind" : "remoteSourceControl", 132 | "location" : "https://github.com/pointfreeco/swiftui-navigation", 133 | "state" : { 134 | "revision" : "d9e72f3083c08375794afa216fb2f89c0114f303", 135 | "version" : "1.2.1" 136 | } 137 | }, 138 | { 139 | "identity" : "xctest-dynamic-overlay", 140 | "kind" : "remoteSourceControl", 141 | "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", 142 | "state" : { 143 | "revision" : "b58e6627149808b40634c4552fcf2f44d0b3ca87", 144 | "version" : "1.1.0" 145 | } 146 | } 147 | ], 148 | "version" : 2 149 | } 150 | -------------------------------------------------------------------------------- /ComposableDependencies/ComposableDependencies/Features.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Features.swift 3 | // ComposableDependencies 4 | // 5 | // Created by Lucas van Dongen on 06/03/2024. 6 | // 7 | 8 | import ComposableArchitecture 9 | import SharedDependencies 10 | 11 | struct Session: Equatable { 12 | let token: String 13 | } 14 | 15 | @Reducer(state: .equatable) 16 | enum AppRootFeature { 17 | case authenticated(AuthenticatedFeature) 18 | case logIn(LogInFeature) 19 | 20 | public static var body: some ReducerOf { 21 | Reduce { state, action in 22 | switch action { 23 | case let .logIn(.authenticatedSuccessfully(token)): 24 | state = .authenticated(AuthenticatedFeature.State(token: token)) 25 | return .none 26 | case .logIn: 27 | return .none // Ignore the rest 28 | case .authenticated: 29 | return .none // Ignore unless we would have log out functionality 30 | } 31 | } 32 | .ifCaseLet(\.logIn, action: \.logIn) { 33 | LogInFeature() 34 | } 35 | .ifCaseLet(\.authenticated, action: \.authenticated) { 36 | AuthenticatedFeature() 37 | // .dependency(\.userManager, UserManager(token: token) 38 | // .dependency(\.storyFetcher, .StoryFetcher(token: token) 39 | }._printChanges() 40 | } 41 | } 42 | 43 | @Reducer 44 | struct AuthenticatedFeature { 45 | @ObservableState 46 | struct State: Equatable { 47 | let token: String 48 | } 49 | 50 | enum Action { 51 | case logOut 52 | } 53 | 54 | var body: some Reducer { 55 | Reduce { state, action in 56 | switch action { 57 | case .logOut: 58 | return .none 59 | } 60 | } 61 | } 62 | } 63 | 64 | @Reducer 65 | struct LogInFeature { 66 | @Dependency(\.authentication) var authentication 67 | 68 | @ObservableState 69 | enum State: Equatable { 70 | case waiting 71 | case authenticating 72 | } 73 | 74 | enum Action { 75 | case logIn 76 | case authenticationError(Error) 77 | case authenticatedSuccessfully(token: String) 78 | } 79 | 80 | var body: some Reducer { 81 | Reduce { state, action in 82 | switch action { 83 | case .logIn: 84 | state = .authenticating 85 | return .run { send in 86 | do { 87 | let token = try await authentication.authenticate() 88 | await send(.authenticatedSuccessfully(token: token)) 89 | } catch let error { 90 | await send(.authenticationError(error)) 91 | } 92 | } 93 | case .authenticationError: 94 | return .none // Not handled ATM 95 | case .authenticatedSuccessfully: 96 | return .none // Only interesting for root feature 97 | } 98 | } 99 | } 100 | } 101 | 102 | @Reducer 103 | struct StoriesFeature { 104 | @Dependency(\.storyFetcher) var storyFetcher 105 | 106 | @ObservableState 107 | enum State: Equatable { 108 | case loading 109 | case failed(reason: String) 110 | case loaded(stories: [Story]) 111 | } 112 | 113 | enum Action { 114 | case startLoading 115 | case loaded(stories: [Story]) 116 | } 117 | 118 | var body: some Reducer { 119 | Reduce { state, action in 120 | switch action { 121 | case .startLoading: 122 | return .run { send in 123 | do { 124 | let stories = try await storyFetcher.fetchStories() 125 | await send(.loaded(stories: stories)) 126 | } catch { 127 | // We're ignoring error handling for now 128 | } 129 | } 130 | case let .loaded(stories): 131 | state = .loaded(stories: stories) 132 | return .none 133 | } 134 | } 135 | } 136 | } 137 | 138 | @Reducer 139 | struct UserManagementFeature { 140 | @Dependency(\.userManager) var userManager 141 | 142 | @ObservableState 143 | enum State: Equatable { 144 | case loaded 145 | case updating 146 | case failed(reason: String) 147 | case updated 148 | } 149 | 150 | enum Action { 151 | case update 152 | case failed(reason: String) 153 | case updated 154 | } 155 | 156 | var body: some Reducer { 157 | Reduce { state, action in 158 | switch action { 159 | case .update: 160 | state = .updating 161 | 162 | return .run { send in 163 | do { 164 | _ = try await userManager.update(user: "") 165 | await send(.updated) 166 | } catch { 167 | // Ignore for now 168 | } 169 | } 170 | case let .failed(reason): 171 | state = .failed(reason: reason) 172 | return .none 173 | case .updated: 174 | state = .updated 175 | return .none 176 | } 177 | } 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /NeedleDependencies/NeedleDependencies/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // NeedleDependencies 4 | // 5 | // Created by Lucas van Dongen on 12/03/2024. 6 | // 7 | 8 | import SharedDependencies 9 | import SwiftUI 10 | 11 | @MainActor 12 | struct AuthenticatedView: View { 13 | let logInSwitcher: any LogInSwitching 14 | let component: AuthenticatedComponent 15 | 16 | @State private var isLoggingOut = false 17 | 18 | var body: some View { 19 | VStack { 20 | // AuthenticatedView needs to know what dependencies UserManagementView and StoriesView need 21 | // A small burden now, but it will increase exponentially with the app's complexity 22 | component.userManagementView 23 | component.storiesView 24 | Button { 25 | isLoggingOut = true 26 | } label: { 27 | Text("Log Out") 28 | }.task(id: isLoggingOut, priority: .high) { 29 | guard isLoggingOut else { 30 | return 31 | } 32 | 33 | defer { 34 | isLoggingOut = false 35 | } 36 | 37 | await logInSwitcher.loggedOut() 38 | } 39 | } 40 | } 41 | } 42 | 43 | @MainActor 44 | struct UserManagementView: View { 45 | private enum ViewState: Equatable { 46 | case loaded 47 | case updating 48 | case failed(reason: String) 49 | case updated 50 | } 51 | 52 | @State private var state: ViewState = .loaded 53 | 54 | let userManager: any UserManaging 55 | 56 | var body: some View { 57 | VStack { 58 | Text("You are logged in with token \(userManager.token)") 59 | 60 | switch state { 61 | case .loaded: 62 | Button { 63 | state = .updating 64 | } label: { 65 | Text("Update User") 66 | } 67 | case .updating: 68 | HStack { 69 | Text("Updating User...") 70 | ProgressView() 71 | } 72 | case let .failed(reason): 73 | Text("Failed updating User:\n\(reason)") 74 | case .updated: 75 | Text("You have updated your user successfully") 76 | } 77 | }.task(id: state, priority: .high) { 78 | guard state == .updating else { 79 | return 80 | } 81 | 82 | do { 83 | _ = try await userManager.update(user: "") 84 | state = .updated 85 | } catch { 86 | // Ignore for now 87 | } 88 | } 89 | } 90 | } 91 | 92 | @MainActor 93 | struct StoriesView: View { 94 | private enum LoadingState { 95 | case fetching 96 | case failed(reason: String) 97 | case fetched(stories: [Story]) 98 | } 99 | 100 | @State private var state: LoadingState = .fetching 101 | 102 | let storyFetcher: any StoryFetching 103 | 104 | var body: some View { 105 | switch state { 106 | case .fetching: 107 | HStack { 108 | Text("Fetching stories...") 109 | ProgressView() 110 | } 111 | .task { 112 | state = .fetching 113 | do { 114 | let stories = try await storyFetcher.fetchStories() 115 | state = .fetched(stories: stories) // You can safely mutate state properties from any thread. 116 | } catch let error { 117 | state = .failed(reason: error.localizedDescription) 118 | } 119 | } 120 | case let .failed(reason): 121 | Text("Failed fetching stories:\n\(reason)") 122 | case let .fetched(stories): 123 | List { 124 | ForEach(stories, id: \.name) { story in 125 | Text("Author: \(story.author)\nName: \(story.name)") 126 | } 127 | } 128 | } 129 | } 130 | } 131 | 132 | @MainActor 133 | struct LogInView: View { 134 | let authentication: Authenticating 135 | let logInSwitcher: any LogInSwitching 136 | 137 | @State private var isAuthenticating = false 138 | 139 | var body: some View { 140 | switch isAuthenticating { 141 | case true: 142 | HStack { 143 | Text("Authenticating...") 144 | ProgressView() 145 | } 146 | case false: 147 | VStack { 148 | Text("You are logged out now") 149 | Button { 150 | Task { 151 | await authenticate() 152 | } 153 | } label: { 154 | Text("Log In") 155 | } 156 | } 157 | } 158 | } 159 | 160 | private func authenticate() async { 161 | isAuthenticating = true 162 | 163 | defer { 164 | isAuthenticating = false 165 | } 166 | 167 | do { 168 | let token = try await authentication.authenticate() 169 | await logInSwitcher.tokenChannel.send(token) 170 | } catch { 171 | // Not implemented 172 | } 173 | } 174 | } 175 | 176 | enum AppState { 177 | case loggedOut 178 | case authenticated(token: String) 179 | } 180 | 181 | @MainActor 182 | class AppViewModel: ObservableObject { 183 | @Published private(set) var state: AppState = .loggedOut 184 | 185 | private let logInSwitcher: any LogInSwitching 186 | 187 | init(logInSwitcher: any LogInSwitching) { 188 | self.logInSwitcher = logInSwitcher 189 | 190 | Task.detached { [weak self] in 191 | await self?.observe(logInSwitcher: logInSwitcher) 192 | } 193 | } 194 | 195 | private func observe(logInSwitcher: any LogInSwitching) async { 196 | for await token in logInSwitcher.tokenChannel { 197 | state = switch token.isEmpty { 198 | case true: .loggedOut 199 | case false: .authenticated(token: token) 200 | } 201 | } 202 | } 203 | } 204 | 205 | @MainActor 206 | struct AppView: View { 207 | @StateObject var viewModel: AppViewModel 208 | 209 | let rootComponent: RootComponent 210 | let logInComponent: LogInComponent 211 | 212 | var body: some View { 213 | switch viewModel.state { 214 | case let .authenticated(token): 215 | rootComponent.authenticatedComponent(token: token) 216 | .authenticatedView 217 | case .loggedOut: 218 | logInComponent.logInView 219 | } 220 | } 221 | } 222 | 223 | struct ContentView: View { 224 | @State private var rootComponent = RootComponent() 225 | 226 | var body: some View { 227 | rootComponent.appView 228 | } 229 | } 230 | 231 | #Preview { 232 | ContentView() 233 | } 234 | -------------------------------------------------------------------------------- /FactoryDependencies/FactoryDependencies/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // FactoryDependencies 4 | // 5 | // Created by Lucas van Dongen on 12/03/2024. 6 | // 7 | 8 | import Factory 9 | import SharedDependencies 10 | import SwiftUI 11 | 12 | @MainActor 13 | struct AuthenticatedView: View { 14 | @Injected(\.logInSwitcher) private var logInSwitcher 15 | 16 | @State private var isLoggingOut = false 17 | 18 | var body: some View { 19 | VStack { 20 | // No dependencies are passed here, making it easier to modularize your application 21 | UserManagementView() 22 | StoriesView() 23 | Button { 24 | isLoggingOut = true 25 | } label: { 26 | Text("Log Out") 27 | }.task(id: isLoggingOut, priority: .high) { 28 | guard isLoggingOut else { 29 | return 30 | } 31 | 32 | defer { 33 | isLoggingOut = false 34 | } 35 | 36 | await logInSwitcher.loggedOut() 37 | } 38 | } 39 | } 40 | } 41 | 42 | @MainActor 43 | struct UserManagementView: View { 44 | private enum ViewState: Equatable { 45 | case loaded 46 | case updating 47 | case failed(reason: String) 48 | case updated 49 | } 50 | 51 | @State private var state: ViewState = .loaded 52 | 53 | @Injected(\.userManager) private var userManager 54 | 55 | var body: some View { 56 | VStack { 57 | Text("You are logged in with token \(userManager.token)") 58 | 59 | switch state { 60 | case .loaded: 61 | Button { 62 | state = .updating 63 | } label: { 64 | Text("Update User") 65 | } 66 | case .updating: 67 | HStack { 68 | Text("Updating User...") 69 | ProgressView() 70 | } 71 | case let .failed(reason): 72 | Text("Failed updating User:\n\(reason)") 73 | case .updated: 74 | Text("You have updated your user successfully") 75 | } 76 | }.task(id: state, priority: .high) { 77 | guard state == .updating else { 78 | return 79 | } 80 | 81 | do { 82 | _ = try await userManager.update(user: "") 83 | state = .updated 84 | } catch { 85 | // Ignore for now 86 | } 87 | } 88 | } 89 | } 90 | 91 | @MainActor 92 | struct StoriesView: View { 93 | private enum LoadingState { 94 | case fetching 95 | case failed(reason: String) 96 | case fetched(stories: [Story]) 97 | } 98 | 99 | @State private var state: LoadingState = .fetching 100 | 101 | @Injected(\.storyFetcher) private var storyFetcher 102 | 103 | var body: some View { 104 | switch state { 105 | case .fetching: 106 | HStack { 107 | Text("Fetching stories...") 108 | ProgressView() 109 | } 110 | .task { 111 | state = .fetching 112 | do { 113 | let stories = try await storyFetcher.fetchStories() 114 | state = .fetched(stories: stories) // You can safely mutate state properties from any thread. 115 | } catch let error { 116 | state = .failed(reason: error.localizedDescription) 117 | } 118 | } 119 | case let .failed(reason): 120 | Text("Failed fetching stories:\n\(reason)") 121 | case let .fetched(stories): 122 | List { 123 | ForEach(stories, id: \.name) { story in 124 | Text("Author: \(story.author)\nName: \(story.name)") 125 | } 126 | } 127 | } 128 | } 129 | } 130 | 131 | @MainActor 132 | struct LogInView: View { 133 | @Injected(\.authentication) private var authentication 134 | @Injected(\.logInSwitcher) private var logInSwitcher 135 | 136 | @State private var isAuthenticating = false 137 | 138 | var body: some View { 139 | switch isAuthenticating { 140 | case true: 141 | HStack { 142 | Text("Authenticating...") 143 | ProgressView() 144 | } 145 | case false: 146 | VStack { 147 | Text("You are logged out now") 148 | Button { 149 | Task { 150 | await authenticate() 151 | } 152 | } label: { 153 | Text("Log In") 154 | } 155 | } 156 | } 157 | } 158 | 159 | private func authenticate() async { 160 | isAuthenticating = true 161 | 162 | defer { 163 | isAuthenticating = false 164 | } 165 | 166 | do { 167 | let token = try await authentication.authenticate() 168 | await logInSwitcher.tokenChannel.send(token) 169 | } catch { 170 | // Not implemented 171 | } 172 | } 173 | } 174 | 175 | import Combine 176 | 177 | @MainActor 178 | class AppViewModel: ObservableObject { 179 | @Published private(set) var state: AppState = .loggedOut 180 | 181 | @Injected(\.logInSwitcher) private var logInSwitcher 182 | 183 | private var cancelBag = Set() 184 | 185 | init() { 186 | Task.detached { [weak self] in 187 | guard 188 | let self 189 | else { 190 | return 191 | } 192 | 193 | await observe(logInSwitcher: await logInSwitcher) 194 | } 195 | } 196 | 197 | private func observe(logInSwitcher: any LogInSwitching) async { 198 | for await token in logInSwitcher.tokenChannel { 199 | // First assign the dependencies 200 | AuthenticatedDependenciesManager.handle(token: token) 201 | 202 | // Then flip the UI switch 203 | state = switch token.isEmpty { 204 | case true: .loggedOut 205 | case false: .authenticated(token: token) 206 | } 207 | 208 | // If I would have these two steps reversed it would be broken, so slightly brittle 209 | } 210 | } 211 | } 212 | 213 | @MainActor 214 | struct AppView: View { 215 | @StateObject var viewModel = AppViewModel() // No dependencies needed 216 | 217 | var body: some View { 218 | // Dependencies are not passed 219 | switch viewModel.state { 220 | case .authenticated: 221 | AuthenticatedView() 222 | case .loggedOut: 223 | LogInView() 224 | } 225 | } 226 | } 227 | 228 | struct ContentView: View { 229 | var body: some View { 230 | AppView() 231 | } 232 | } 233 | 234 | #Preview { 235 | ContentView() 236 | } 237 | -------------------------------------------------------------------------------- /EnvironmentDependencies/EnvironmentDependencies/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // EnvironmentDependencies 4 | // 5 | // Created by Lucas van Dongen on 15/03/2024. 6 | // 7 | 8 | import SharedDependencies 9 | import SwiftUI 10 | 11 | @MainActor 12 | struct AuthenticatedView: View { 13 | @Environment(\.logInSwitcher) private var logInSwitcher: LogInSwitching 14 | 15 | @State private var isLoggingOut = false 16 | 17 | var body: some View { 18 | VStack { 19 | // Here, we need to assume the right environment values were set the moment we got the token 20 | // If we would have multiple Views consuming the same dependencies, it would save a lot of work 21 | // When not set, we would have a crash here 22 | UserManagementView() 23 | StoriesView() 24 | Button { 25 | isLoggingOut = true 26 | } label: { 27 | Text("Log Out") 28 | }.task(id: isLoggingOut, priority: .high) { 29 | guard isLoggingOut else { 30 | return 31 | } 32 | 33 | defer { 34 | isLoggingOut = false 35 | } 36 | 37 | await logInSwitcher.loggedOut() 38 | } 39 | } 40 | } 41 | } 42 | 43 | @MainActor 44 | struct UserManagementView: View { 45 | private enum ViewState: Equatable { 46 | case loaded 47 | case updating 48 | case failed(reason: String) 49 | case updated 50 | } 51 | 52 | @State private var state: ViewState = .loaded 53 | 54 | @Environment(\.userManager) private var userManager: UserManaging 55 | 56 | var body: some View { 57 | VStack { 58 | Text("You are logged in with token \(userManager.token)") 59 | switch state { 60 | case .loaded: 61 | Button { 62 | state = .updating 63 | } label: { 64 | Text("Update User") 65 | } 66 | case .updating: 67 | HStack { 68 | Text("Updating User...") 69 | ProgressView() 70 | } 71 | case let .failed(reason): 72 | Text("Failed updating User:\n\(reason)") 73 | case .updated: 74 | Text("You have updated your user successfully") 75 | } 76 | }.task(id: state, priority: .high) { 77 | guard state == .updating else { 78 | return 79 | } 80 | 81 | do { 82 | _ = try await userManager.update(user: "") 83 | state = .updated 84 | } catch { 85 | // Ignore for now 86 | } 87 | } 88 | } 89 | } 90 | 91 | @MainActor 92 | struct StoriesView: View { 93 | private enum LoadingState { 94 | case fetching 95 | case failed(reason: String) 96 | case fetched(stories: [Story]) 97 | } 98 | 99 | @State private var state: LoadingState = .fetching 100 | 101 | @Environment(StoryFetcher.self) private var storyFetcher: StoryFetcher 102 | 103 | var body: some View { 104 | switch state { 105 | case .fetching: 106 | HStack { 107 | Text("Fetching stories...") 108 | ProgressView() 109 | } 110 | .task { 111 | state = .fetching 112 | do { 113 | let stories = try await storyFetcher.fetchStories() 114 | state = .fetched(stories: stories) // You can safely mutate state properties from any thread. 115 | } catch let error { 116 | state = .failed(reason: error.localizedDescription) 117 | } 118 | } 119 | case let .failed(reason): 120 | Text("Failed fetching stories:\n\(reason)") 121 | case let .fetched(stories): 122 | List { 123 | ForEach(stories, id: \.name) { story in 124 | Text("Author: \(story.author)\nName: \(story.name)") 125 | } 126 | } 127 | } 128 | } 129 | } 130 | 131 | @MainActor 132 | struct LogInView: View { 133 | @Environment(\.authentication) private var authentication: Authenticating 134 | @Environment(\.logInSwitcher) private var logInSwitcher: LogInSwitching 135 | 136 | @State private var isAuthenticating = false 137 | 138 | var body: some View { 139 | switch isAuthenticating { 140 | case true: 141 | HStack { 142 | Text("Authenticating...") 143 | ProgressView() 144 | } 145 | case false: 146 | VStack { 147 | Text("You are logged out now") 148 | Button { 149 | Task.detached { 150 | await authenticate() 151 | } 152 | } label: { 153 | Text("Log In") 154 | } 155 | } 156 | } 157 | } 158 | 159 | private func authenticate() async { 160 | isAuthenticating = true 161 | 162 | defer { 163 | isAuthenticating = false 164 | } 165 | 166 | do { 167 | let token = try await authentication.authenticate() 168 | await logInSwitcher.tokenChannel.send(token) 169 | } catch { 170 | // Not implemented 171 | } 172 | } 173 | } 174 | 175 | @MainActor 176 | class AppViewModel: ObservableObject { 177 | @Published private(set) var state: AppState = .loggedOut 178 | 179 | init(logInSwitcher: LogInSwitching) { 180 | Task.detached { [weak self] in 181 | await self?.observe(logInSwitcher: logInSwitcher) 182 | } 183 | } 184 | 185 | private func observe(logInSwitcher: LogInSwitching) async { 186 | for await token in logInSwitcher.tokenChannel { 187 | state = switch token.isEmpty { 188 | case true: .loggedOut 189 | case false: .authenticated(token: token) 190 | } 191 | } 192 | } 193 | } 194 | 195 | @MainActor 196 | struct AppView: View { 197 | @StateObject var viewModel: AppViewModel 198 | 199 | var body: some View { 200 | switch viewModel.state { 201 | case let .authenticated(token): 202 | // AppView is now responsible for passing the right dependencies into `environment` or `environmentObject` 203 | // Failing to set the `UserManager` will result in the `PlaceholderUserManager` being used 204 | // Failing to set the `StoryFetcher` will result in a crash when it's accessed 205 | // It does work really well to keep certain dependencies only in one part of the tree 206 | AuthenticatedView() 207 | .environment(\.userManager, UserManager(token: token)) 208 | .environment(StoryFetcher(token: token)) 209 | case .loggedOut: 210 | LogInView() 211 | } 212 | } 213 | } 214 | 215 | @MainActor 216 | struct ContentView: View { 217 | @Environment(\.logInSwitcher) private var logInSwitcher: LogInSwitching 218 | 219 | var body: some View { 220 | AppView(viewModel: AppViewModel(logInSwitcher: logInSwitcher)) 221 | } 222 | } 223 | 224 | #Preview { 225 | ContentView() 226 | } 227 | -------------------------------------------------------------------------------- /PassedDependencies/PassedDependencies/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // PassedDependencies 4 | // 5 | // Created by Lucas van Dongen on 06/03/2024. 6 | // 7 | 8 | import SharedDependencies 9 | import SwiftUI 10 | 11 | @MainActor 12 | struct AuthenticatedView: View { 13 | let dependencies: AuthenticatedDependenciesContaining 14 | 15 | @State private var isLoggingOut = false 16 | 17 | var body: some View { 18 | VStack { 19 | // AuthenticatedView needs to know what dependencies UserManagementView and StoriesView need 20 | // A small burden now, but it will increase exponentially with the app's complexity 21 | UserManagementView(userManager: dependencies.userManager) 22 | StoriesView(storyFetcher: dependencies.storyFetcher) 23 | Button { 24 | isLoggingOut = true 25 | } label: { 26 | Text("Log Out") 27 | }.task(id: isLoggingOut, priority: .high) { 28 | guard isLoggingOut else { 29 | return 30 | } 31 | 32 | defer { 33 | isLoggingOut = false 34 | } 35 | 36 | await dependencies.logInSwitcher.loggedOut() 37 | } 38 | } 39 | } 40 | } 41 | 42 | @MainActor 43 | struct UserManagementView: View { 44 | private enum ViewState: Equatable { 45 | case loaded 46 | case updating 47 | case failed(reason: String) 48 | case updated 49 | } 50 | 51 | @State private var state: ViewState = .loaded 52 | 53 | let userManager: any UserManaging 54 | 55 | var body: some View { 56 | VStack { 57 | Text("You are logged in with token \(userManager.token)") 58 | 59 | switch state { 60 | case .loaded: 61 | Button { 62 | state = .updating 63 | } label: { 64 | Text("Update User") 65 | } 66 | case .updating: 67 | HStack { 68 | Text("Updating User...") 69 | ProgressView() 70 | } 71 | case let .failed(reason): 72 | Text("Failed updating User:\n\(reason)") 73 | case .updated: 74 | Text("You have updated your user successfully") 75 | } 76 | }.task(id: state, priority: .high) { 77 | guard state == .updating else { 78 | return 79 | } 80 | 81 | do { 82 | _ = try await userManager.update(user: "") 83 | state = .updated 84 | } catch { 85 | // Ignore for now 86 | } 87 | } 88 | } 89 | } 90 | 91 | @MainActor 92 | struct StoriesView: View { 93 | private enum LoadingState { 94 | case fetching 95 | case failed(reason: String) 96 | case fetched(stories: [Story]) 97 | } 98 | 99 | @State private var state: LoadingState = .fetching 100 | 101 | let storyFetcher: any StoryFetching 102 | 103 | var body: some View { 104 | switch state { 105 | case .fetching: 106 | HStack { 107 | Text("Fetching stories...") 108 | ProgressView() 109 | } 110 | .task { 111 | state = .fetching 112 | do { 113 | let stories = try await storyFetcher.fetchStories() 114 | state = .fetched(stories: stories) // You can safely mutate state properties from any thread. 115 | } catch let error { 116 | state = .failed(reason: error.localizedDescription) 117 | } 118 | } 119 | case let .failed(reason): 120 | Text("Failed fetching stories:\n\(reason)") 121 | case let .fetched(stories): 122 | List { 123 | ForEach(stories, id: \.name) { story in 124 | Text("Author: \(story.author)\nName: \(story.name)") 125 | } 126 | } 127 | } 128 | } 129 | } 130 | 131 | @MainActor 132 | struct LogInView: View { 133 | let dependencies: LogInDependenciesContaining 134 | 135 | @State private var isAuthenticating = false 136 | @State private var tapped = 0 137 | 138 | var body: some View { 139 | Group { 140 | switch isAuthenticating { 141 | case true: 142 | VStack { 143 | HStack { 144 | Text("Authenticating...") 145 | ProgressView() 146 | } 147 | } 148 | case false: 149 | VStack { 150 | Text("You are logged out now") 151 | Button { 152 | Task { 153 | await authenticate() 154 | } 155 | } label: { 156 | Text("Log In") 157 | } 158 | } 159 | } 160 | } 161 | } 162 | 163 | private func authenticate() async { 164 | isAuthenticating = true 165 | 166 | defer { 167 | isAuthenticating = false 168 | } 169 | 170 | do { 171 | let token = try await dependencies.authentication.authenticate() 172 | await dependencies.logInSwitcher.tokenChannel.send(token) 173 | } catch { 174 | // Not implemented 175 | } 176 | } 177 | } 178 | 179 | @MainActor 180 | class AppViewModel: ObservableObject { 181 | @Published private(set) var state: AppState = .loggedOut 182 | 183 | let logInDependencies: LogInDependenciesContaining 184 | 185 | init(logInDependencies: LogInDependenciesContaining) { 186 | self.logInDependencies = logInDependencies 187 | 188 | let logInSwitcher = logInDependencies.logInSwitcher 189 | 190 | Task.detached { [weak self] in 191 | await self?.observe(logInSwitcher: logInSwitcher) 192 | } 193 | } 194 | 195 | private func observe(logInSwitcher: any LogInSwitching) async { 196 | for await token in logInSwitcher.tokenChannel { 197 | state = switch token.isEmpty { 198 | case true: .loggedOut 199 | case false: .authenticated(token: token) 200 | } 201 | } 202 | } 203 | } 204 | 205 | @MainActor 206 | struct AppView: View { 207 | @StateObject var viewModel: AppViewModel 208 | 209 | // Clearly the AppView knows a lot about logging in - too much perhaps 210 | private let logInDependencies: LogInDependenciesContaining 211 | 212 | init( 213 | dependencies: LogInDependencies 214 | ) { 215 | _viewModel = StateObject(wrappedValue: AppViewModel(logInDependencies: dependencies)) 216 | self.logInDependencies = dependencies 217 | } 218 | 219 | var body: some View { 220 | switch viewModel.state { 221 | case let .authenticated(token): 222 | // Watch out: the dependencies get recreated every time the View gets re-rendered 223 | // Is this what you really want? Only when your dependencies are truly stateless! 224 | AuthenticatedView( 225 | dependencies: buildAuthenticatedDependencies(for: token) 226 | ) 227 | case .loggedOut: 228 | LogInView(dependencies: logInDependencies) 229 | } 230 | } 231 | 232 | private func buildAuthenticatedDependencies(for token: String) -> AuthenticatedDependencies { 233 | AuthenticatedDependencies( 234 | token: token, 235 | logInSwitcher: logInDependencies.logInSwitcher 236 | ) 237 | } 238 | } 239 | 240 | @MainActor 241 | struct ContentView: View { 242 | var body: some View { 243 | AppView(dependencies: LogInDependencies()) 244 | } 245 | } 246 | 247 | #Preview { 248 | ContentView() 249 | } 250 | -------------------------------------------------------------------------------- /FactoryDependencies/FactoryDependencies.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 60; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | A0107A1A2BA0809C00D3A35B /* FactoryDependenciesApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0107A192BA0809C00D3A35B /* FactoryDependenciesApp.swift */; }; 11 | A0107A1C2BA0809C00D3A35B /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0107A1B2BA0809C00D3A35B /* ContentView.swift */; }; 12 | A0107A1E2BA0809E00D3A35B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A0107A1D2BA0809E00D3A35B /* Assets.xcassets */; }; 13 | A0107A212BA0809E00D3A35B /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A0107A202BA0809E00D3A35B /* Preview Assets.xcassets */; }; 14 | A0107A2B2BA080D600D3A35B /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0107A2A2BA080D600D3A35B /* Container.swift */; }; 15 | A0107A2F2BA080FE00D3A35B /* Model.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0107A2E2BA080FE00D3A35B /* Model.swift */; }; 16 | A0107A392BA08C4000D3A35B /* SharedDependencies in Frameworks */ = {isa = PBXBuildFile; productRef = A0107A382BA08C4000D3A35B /* SharedDependencies */; }; 17 | CAFD9B712BB2371F00B35F4A /* Factory in Frameworks */ = {isa = PBXBuildFile; productRef = CAFD9B702BB2371F00B35F4A /* Factory */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXFileReference section */ 21 | A0107A162BA0809C00D3A35B /* FactoryDependencies.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FactoryDependencies.app; sourceTree = BUILT_PRODUCTS_DIR; }; 22 | A0107A192BA0809C00D3A35B /* FactoryDependenciesApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FactoryDependenciesApp.swift; sourceTree = ""; }; 23 | A0107A1B2BA0809C00D3A35B /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 24 | A0107A1D2BA0809E00D3A35B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 25 | A0107A202BA0809E00D3A35B /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 26 | A0107A222BA0809E00D3A35B /* FactoryDependencies.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = FactoryDependencies.entitlements; sourceTree = ""; }; 27 | A0107A2A2BA080D600D3A35B /* Container.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = ""; }; 28 | A0107A2E2BA080FE00D3A35B /* Model.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Model.swift; sourceTree = ""; }; 29 | A0107A312BA0819800D3A35B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 30 | /* End PBXFileReference section */ 31 | 32 | /* Begin PBXFrameworksBuildPhase section */ 33 | A0107A132BA0809C00D3A35B /* Frameworks */ = { 34 | isa = PBXFrameworksBuildPhase; 35 | buildActionMask = 2147483647; 36 | files = ( 37 | A0107A392BA08C4000D3A35B /* SharedDependencies in Frameworks */, 38 | CAFD9B712BB2371F00B35F4A /* Factory in Frameworks */, 39 | ); 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXFrameworksBuildPhase section */ 43 | 44 | /* Begin PBXGroup section */ 45 | A0107A0D2BA0809C00D3A35B = { 46 | isa = PBXGroup; 47 | children = ( 48 | A0107A182BA0809C00D3A35B /* FactoryDependencies */, 49 | A0107A172BA0809C00D3A35B /* Products */, 50 | A0107A332BA0846D00D3A35B /* Frameworks */, 51 | ); 52 | sourceTree = ""; 53 | }; 54 | A0107A172BA0809C00D3A35B /* Products */ = { 55 | isa = PBXGroup; 56 | children = ( 57 | A0107A162BA0809C00D3A35B /* FactoryDependencies.app */, 58 | ); 59 | name = Products; 60 | sourceTree = ""; 61 | }; 62 | A0107A182BA0809C00D3A35B /* FactoryDependencies */ = { 63 | isa = PBXGroup; 64 | children = ( 65 | A0107A312BA0819800D3A35B /* Info.plist */, 66 | A0107A2A2BA080D600D3A35B /* Container.swift */, 67 | A0107A192BA0809C00D3A35B /* FactoryDependenciesApp.swift */, 68 | A0107A1B2BA0809C00D3A35B /* ContentView.swift */, 69 | A0107A2E2BA080FE00D3A35B /* Model.swift */, 70 | A0107A1D2BA0809E00D3A35B /* Assets.xcassets */, 71 | A0107A222BA0809E00D3A35B /* FactoryDependencies.entitlements */, 72 | A0107A1F2BA0809E00D3A35B /* Preview Content */, 73 | ); 74 | path = FactoryDependencies; 75 | sourceTree = ""; 76 | }; 77 | A0107A1F2BA0809E00D3A35B /* Preview Content */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | A0107A202BA0809E00D3A35B /* Preview Assets.xcassets */, 81 | ); 82 | path = "Preview Content"; 83 | sourceTree = ""; 84 | }; 85 | A0107A332BA0846D00D3A35B /* Frameworks */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | ); 89 | name = Frameworks; 90 | sourceTree = ""; 91 | }; 92 | /* End PBXGroup section */ 93 | 94 | /* Begin PBXNativeTarget section */ 95 | A0107A152BA0809C00D3A35B /* FactoryDependencies */ = { 96 | isa = PBXNativeTarget; 97 | buildConfigurationList = A0107A252BA0809E00D3A35B /* Build configuration list for PBXNativeTarget "FactoryDependencies" */; 98 | buildPhases = ( 99 | A0107A122BA0809C00D3A35B /* Sources */, 100 | A0107A132BA0809C00D3A35B /* Frameworks */, 101 | A0107A142BA0809C00D3A35B /* Resources */, 102 | ); 103 | buildRules = ( 104 | ); 105 | dependencies = ( 106 | ); 107 | name = FactoryDependencies; 108 | packageProductDependencies = ( 109 | A0107A382BA08C4000D3A35B /* SharedDependencies */, 110 | CAFD9B702BB2371F00B35F4A /* Factory */, 111 | ); 112 | productName = FactoryDependencies; 113 | productReference = A0107A162BA0809C00D3A35B /* FactoryDependencies.app */; 114 | productType = "com.apple.product-type.application"; 115 | }; 116 | /* End PBXNativeTarget section */ 117 | 118 | /* Begin PBXProject section */ 119 | A0107A0E2BA0809C00D3A35B /* Project object */ = { 120 | isa = PBXProject; 121 | attributes = { 122 | BuildIndependentTargetsInParallel = 1; 123 | LastSwiftUpdateCheck = 1520; 124 | LastUpgradeCheck = 1530; 125 | TargetAttributes = { 126 | A0107A152BA0809C00D3A35B = { 127 | CreatedOnToolsVersion = 15.2; 128 | }; 129 | }; 130 | }; 131 | buildConfigurationList = A0107A112BA0809C00D3A35B /* Build configuration list for PBXProject "FactoryDependencies" */; 132 | compatibilityVersion = "Xcode 14.0"; 133 | developmentRegion = en; 134 | hasScannedForEncodings = 0; 135 | knownRegions = ( 136 | en, 137 | Base, 138 | ); 139 | mainGroup = A0107A0D2BA0809C00D3A35B; 140 | packageReferences = ( 141 | A0107A372BA08C4000D3A35B /* XCLocalSwiftPackageReference "../SharedDependencies" */, 142 | CAFD9AC02BB22F6400B35F4A /* XCRemoteSwiftPackageReference "Factory" */, 143 | ); 144 | productRefGroup = A0107A172BA0809C00D3A35B /* Products */; 145 | projectDirPath = ""; 146 | projectRoot = ""; 147 | targets = ( 148 | A0107A152BA0809C00D3A35B /* FactoryDependencies */, 149 | ); 150 | }; 151 | /* End PBXProject section */ 152 | 153 | /* Begin PBXResourcesBuildPhase section */ 154 | A0107A142BA0809C00D3A35B /* Resources */ = { 155 | isa = PBXResourcesBuildPhase; 156 | buildActionMask = 2147483647; 157 | files = ( 158 | A0107A212BA0809E00D3A35B /* Preview Assets.xcassets in Resources */, 159 | A0107A1E2BA0809E00D3A35B /* Assets.xcassets in Resources */, 160 | ); 161 | runOnlyForDeploymentPostprocessing = 0; 162 | }; 163 | /* End PBXResourcesBuildPhase section */ 164 | 165 | /* Begin PBXSourcesBuildPhase section */ 166 | A0107A122BA0809C00D3A35B /* Sources */ = { 167 | isa = PBXSourcesBuildPhase; 168 | buildActionMask = 2147483647; 169 | files = ( 170 | A0107A1C2BA0809C00D3A35B /* ContentView.swift in Sources */, 171 | A0107A2B2BA080D600D3A35B /* Container.swift in Sources */, 172 | A0107A1A2BA0809C00D3A35B /* FactoryDependenciesApp.swift in Sources */, 173 | A0107A2F2BA080FE00D3A35B /* Model.swift in Sources */, 174 | ); 175 | runOnlyForDeploymentPostprocessing = 0; 176 | }; 177 | /* End PBXSourcesBuildPhase section */ 178 | 179 | /* Begin XCBuildConfiguration section */ 180 | A0107A232BA0809E00D3A35B /* Debug */ = { 181 | isa = XCBuildConfiguration; 182 | buildSettings = { 183 | ALWAYS_SEARCH_USER_PATHS = NO; 184 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 185 | CLANG_ANALYZER_NONNULL = YES; 186 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 187 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 188 | CLANG_ENABLE_MODULES = YES; 189 | CLANG_ENABLE_OBJC_ARC = YES; 190 | CLANG_ENABLE_OBJC_WEAK = YES; 191 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 192 | CLANG_WARN_BOOL_CONVERSION = YES; 193 | CLANG_WARN_COMMA = YES; 194 | CLANG_WARN_CONSTANT_CONVERSION = YES; 195 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 196 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 197 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 198 | CLANG_WARN_EMPTY_BODY = YES; 199 | CLANG_WARN_ENUM_CONVERSION = YES; 200 | CLANG_WARN_INFINITE_RECURSION = YES; 201 | CLANG_WARN_INT_CONVERSION = YES; 202 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 203 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 204 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 205 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 206 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 207 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 208 | CLANG_WARN_STRICT_PROTOTYPES = YES; 209 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 210 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 211 | CLANG_WARN_UNREACHABLE_CODE = YES; 212 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 213 | COPY_PHASE_STRIP = NO; 214 | DEAD_CODE_STRIPPING = YES; 215 | DEBUG_INFORMATION_FORMAT = dwarf; 216 | ENABLE_STRICT_OBJC_MSGSEND = YES; 217 | ENABLE_TESTABILITY = YES; 218 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 219 | GCC_C_LANGUAGE_STANDARD = gnu17; 220 | GCC_DYNAMIC_NO_PIC = NO; 221 | GCC_NO_COMMON_BLOCKS = YES; 222 | GCC_OPTIMIZATION_LEVEL = 0; 223 | GCC_PREPROCESSOR_DEFINITIONS = ( 224 | "DEBUG=1", 225 | "$(inherited)", 226 | ); 227 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 228 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 229 | GCC_WARN_UNDECLARED_SELECTOR = YES; 230 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 231 | GCC_WARN_UNUSED_FUNCTION = YES; 232 | GCC_WARN_UNUSED_VARIABLE = YES; 233 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 234 | MACOSX_DEPLOYMENT_TARGET = 14.2; 235 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 236 | MTL_FAST_MATH = YES; 237 | ONLY_ACTIVE_ARCH = YES; 238 | SDKROOT = macosx; 239 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; 240 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 241 | SWIFT_STRICT_CONCURRENCY = complete; 242 | }; 243 | name = Debug; 244 | }; 245 | A0107A242BA0809E00D3A35B /* Release */ = { 246 | isa = XCBuildConfiguration; 247 | buildSettings = { 248 | ALWAYS_SEARCH_USER_PATHS = NO; 249 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 250 | CLANG_ANALYZER_NONNULL = YES; 251 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 252 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 253 | CLANG_ENABLE_MODULES = YES; 254 | CLANG_ENABLE_OBJC_ARC = YES; 255 | CLANG_ENABLE_OBJC_WEAK = YES; 256 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 257 | CLANG_WARN_BOOL_CONVERSION = YES; 258 | CLANG_WARN_COMMA = YES; 259 | CLANG_WARN_CONSTANT_CONVERSION = YES; 260 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 261 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 262 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 263 | CLANG_WARN_EMPTY_BODY = YES; 264 | CLANG_WARN_ENUM_CONVERSION = YES; 265 | CLANG_WARN_INFINITE_RECURSION = YES; 266 | CLANG_WARN_INT_CONVERSION = YES; 267 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 268 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 269 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 270 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 271 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 272 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 273 | CLANG_WARN_STRICT_PROTOTYPES = YES; 274 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 275 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 276 | CLANG_WARN_UNREACHABLE_CODE = YES; 277 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 278 | COPY_PHASE_STRIP = NO; 279 | DEAD_CODE_STRIPPING = YES; 280 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 281 | ENABLE_NS_ASSERTIONS = NO; 282 | ENABLE_STRICT_OBJC_MSGSEND = YES; 283 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 284 | GCC_C_LANGUAGE_STANDARD = gnu17; 285 | GCC_NO_COMMON_BLOCKS = YES; 286 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 287 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 288 | GCC_WARN_UNDECLARED_SELECTOR = YES; 289 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 290 | GCC_WARN_UNUSED_FUNCTION = YES; 291 | GCC_WARN_UNUSED_VARIABLE = YES; 292 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 293 | MACOSX_DEPLOYMENT_TARGET = 14.2; 294 | MTL_ENABLE_DEBUG_INFO = NO; 295 | MTL_FAST_MATH = YES; 296 | SDKROOT = macosx; 297 | SWIFT_COMPILATION_MODE = wholemodule; 298 | SWIFT_STRICT_CONCURRENCY = complete; 299 | }; 300 | name = Release; 301 | }; 302 | A0107A262BA0809E00D3A35B /* Debug */ = { 303 | isa = XCBuildConfiguration; 304 | buildSettings = { 305 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 306 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 307 | CODE_SIGN_ENTITLEMENTS = FactoryDependencies/FactoryDependencies.entitlements; 308 | CODE_SIGN_STYLE = Automatic; 309 | COMBINE_HIDPI_IMAGES = YES; 310 | CURRENT_PROJECT_VERSION = 1; 311 | DEAD_CODE_STRIPPING = YES; 312 | DEVELOPMENT_ASSET_PATHS = "\"FactoryDependencies/Preview Content\""; 313 | DEVELOPMENT_TEAM = 79L7M968L6; 314 | ENABLE_HARDENED_RUNTIME = YES; 315 | ENABLE_PREVIEWS = YES; 316 | GENERATE_INFOPLIST_FILE = YES; 317 | INFOPLIST_FILE = FactoryDependencies/Info.plist; 318 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 319 | LD_RUNPATH_SEARCH_PATHS = ( 320 | "$(inherited)", 321 | "@executable_path/../Frameworks", 322 | ); 323 | MACOSX_DEPLOYMENT_TARGET = 14.0; 324 | MARKETING_VERSION = 1.0; 325 | PRODUCT_BUNDLE_IDENTIFIER = dev.lucasvandongen.FactoryDependencies; 326 | PRODUCT_NAME = "$(TARGET_NAME)"; 327 | SWIFT_EMIT_LOC_STRINGS = YES; 328 | SWIFT_VERSION = 5.0; 329 | }; 330 | name = Debug; 331 | }; 332 | A0107A272BA0809E00D3A35B /* Release */ = { 333 | isa = XCBuildConfiguration; 334 | buildSettings = { 335 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 336 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 337 | CODE_SIGN_ENTITLEMENTS = FactoryDependencies/FactoryDependencies.entitlements; 338 | CODE_SIGN_STYLE = Automatic; 339 | COMBINE_HIDPI_IMAGES = YES; 340 | CURRENT_PROJECT_VERSION = 1; 341 | DEAD_CODE_STRIPPING = YES; 342 | DEVELOPMENT_ASSET_PATHS = "\"FactoryDependencies/Preview Content\""; 343 | DEVELOPMENT_TEAM = 79L7M968L6; 344 | ENABLE_HARDENED_RUNTIME = YES; 345 | ENABLE_PREVIEWS = YES; 346 | GENERATE_INFOPLIST_FILE = YES; 347 | INFOPLIST_FILE = FactoryDependencies/Info.plist; 348 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 349 | LD_RUNPATH_SEARCH_PATHS = ( 350 | "$(inherited)", 351 | "@executable_path/../Frameworks", 352 | ); 353 | MACOSX_DEPLOYMENT_TARGET = 14.0; 354 | MARKETING_VERSION = 1.0; 355 | PRODUCT_BUNDLE_IDENTIFIER = dev.lucasvandongen.FactoryDependencies; 356 | PRODUCT_NAME = "$(TARGET_NAME)"; 357 | SWIFT_EMIT_LOC_STRINGS = YES; 358 | SWIFT_VERSION = 5.0; 359 | }; 360 | name = Release; 361 | }; 362 | /* End XCBuildConfiguration section */ 363 | 364 | /* Begin XCConfigurationList section */ 365 | A0107A112BA0809C00D3A35B /* Build configuration list for PBXProject "FactoryDependencies" */ = { 366 | isa = XCConfigurationList; 367 | buildConfigurations = ( 368 | A0107A232BA0809E00D3A35B /* Debug */, 369 | A0107A242BA0809E00D3A35B /* Release */, 370 | ); 371 | defaultConfigurationIsVisible = 0; 372 | defaultConfigurationName = Release; 373 | }; 374 | A0107A252BA0809E00D3A35B /* Build configuration list for PBXNativeTarget "FactoryDependencies" */ = { 375 | isa = XCConfigurationList; 376 | buildConfigurations = ( 377 | A0107A262BA0809E00D3A35B /* Debug */, 378 | A0107A272BA0809E00D3A35B /* Release */, 379 | ); 380 | defaultConfigurationIsVisible = 0; 381 | defaultConfigurationName = Release; 382 | }; 383 | /* End XCConfigurationList section */ 384 | 385 | /* Begin XCLocalSwiftPackageReference section */ 386 | A0107A372BA08C4000D3A35B /* XCLocalSwiftPackageReference "../SharedDependencies" */ = { 387 | isa = XCLocalSwiftPackageReference; 388 | relativePath = ../SharedDependencies; 389 | }; 390 | /* End XCLocalSwiftPackageReference section */ 391 | 392 | /* Begin XCRemoteSwiftPackageReference section */ 393 | CAFD9AC02BB22F6400B35F4A /* XCRemoteSwiftPackageReference "Factory" */ = { 394 | isa = XCRemoteSwiftPackageReference; 395 | repositoryURL = "http://github.com/hmlongco/Factory"; 396 | requirement = { 397 | kind = upToNextMajorVersion; 398 | minimumVersion = 2.3.2; 399 | }; 400 | }; 401 | /* End XCRemoteSwiftPackageReference section */ 402 | 403 | /* Begin XCSwiftPackageProductDependency section */ 404 | A0107A382BA08C4000D3A35B /* SharedDependencies */ = { 405 | isa = XCSwiftPackageProductDependency; 406 | productName = SharedDependencies; 407 | }; 408 | CAFD9B702BB2371F00B35F4A /* Factory */ = { 409 | isa = XCSwiftPackageProductDependency; 410 | package = CAFD9AC02BB22F6400B35F4A /* XCRemoteSwiftPackageReference "Factory" */; 411 | productName = Factory; 412 | }; 413 | /* End XCSwiftPackageProductDependency section */ 414 | }; 415 | rootObject = A0107A0E2BA0809C00D3A35B /* Project object */; 416 | } 417 | -------------------------------------------------------------------------------- /SwiftDependencies/SwiftDependencies.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 56; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | CAFD9B3F2BB234B700B35F4A /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAFD9B3E2BB234B700B35F4A /* App.swift */; }; 11 | CAFD9B412BB234B700B35F4A /* AppFeature.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAFD9B402BB234B700B35F4A /* AppFeature.swift */; }; 12 | CAFD9B432BB234B800B35F4A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CAFD9B422BB234B800B35F4A /* Assets.xcassets */; }; 13 | CAFD9B462BB234B800B35F4A /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CAFD9B452BB234B800B35F4A /* Preview Assets.xcassets */; }; 14 | CAFD9B6A2BB234C600B35F4A /* SharedDependencies in Frameworks */ = {isa = PBXBuildFile; productRef = CAFD9B692BB234C600B35F4A /* SharedDependencies */; }; 15 | CAFD9B6D2BB234FD00B35F4A /* Dependencies in Frameworks */ = {isa = PBXBuildFile; productRef = CAFD9B6C2BB234FD00B35F4A /* Dependencies */; }; 16 | CAFD9B6F2BB2367800B35F4A /* LoggedOutFeature.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAFD9B6E2BB2367800B35F4A /* LoggedOutFeature.swift */; }; 17 | CAFD9B732BB2375800B35F4A /* Dependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAFD9B722BB2375800B35F4A /* Dependencies.swift */; }; 18 | CAFD9B752BB23AD800B35F4A /* AuthenticatedFeature.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAFD9B742BB23AD800B35F4A /* AuthenticatedFeature.swift */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXFileReference section */ 22 | CAFD9B3B2BB234B700B35F4A /* SwiftDependencies.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftDependencies.app; sourceTree = BUILT_PRODUCTS_DIR; }; 23 | CAFD9B3E2BB234B700B35F4A /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = ""; }; 24 | CAFD9B402BB234B700B35F4A /* AppFeature.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppFeature.swift; sourceTree = ""; }; 25 | CAFD9B422BB234B800B35F4A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 26 | CAFD9B452BB234B800B35F4A /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 27 | CAFD9B6E2BB2367800B35F4A /* LoggedOutFeature.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggedOutFeature.swift; sourceTree = ""; }; 28 | CAFD9B722BB2375800B35F4A /* Dependencies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dependencies.swift; sourceTree = ""; }; 29 | CAFD9B742BB23AD800B35F4A /* AuthenticatedFeature.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticatedFeature.swift; sourceTree = ""; }; 30 | /* End PBXFileReference section */ 31 | 32 | /* Begin PBXFrameworksBuildPhase section */ 33 | CAFD9B382BB234B700B35F4A /* Frameworks */ = { 34 | isa = PBXFrameworksBuildPhase; 35 | buildActionMask = 2147483647; 36 | files = ( 37 | CAFD9B6A2BB234C600B35F4A /* SharedDependencies in Frameworks */, 38 | CAFD9B6D2BB234FD00B35F4A /* Dependencies in Frameworks */, 39 | ); 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXFrameworksBuildPhase section */ 43 | 44 | /* Begin PBXGroup section */ 45 | CAFD9B322BB234B700B35F4A = { 46 | isa = PBXGroup; 47 | children = ( 48 | CAFD9B3D2BB234B700B35F4A /* SwiftDependencies */, 49 | CAFD9B3C2BB234B700B35F4A /* Products */, 50 | CAFD9B682BB234C600B35F4A /* Frameworks */, 51 | ); 52 | sourceTree = ""; 53 | }; 54 | CAFD9B3C2BB234B700B35F4A /* Products */ = { 55 | isa = PBXGroup; 56 | children = ( 57 | CAFD9B3B2BB234B700B35F4A /* SwiftDependencies.app */, 58 | ); 59 | name = Products; 60 | sourceTree = ""; 61 | }; 62 | CAFD9B3D2BB234B700B35F4A /* SwiftDependencies */ = { 63 | isa = PBXGroup; 64 | children = ( 65 | CAFD9B3E2BB234B700B35F4A /* App.swift */, 66 | CAFD9B402BB234B700B35F4A /* AppFeature.swift */, 67 | CAFD9B742BB23AD800B35F4A /* AuthenticatedFeature.swift */, 68 | CAFD9B722BB2375800B35F4A /* Dependencies.swift */, 69 | CAFD9B6E2BB2367800B35F4A /* LoggedOutFeature.swift */, 70 | CAFD9B422BB234B800B35F4A /* Assets.xcassets */, 71 | CAFD9B442BB234B800B35F4A /* Preview Content */, 72 | ); 73 | path = SwiftDependencies; 74 | sourceTree = ""; 75 | }; 76 | CAFD9B442BB234B800B35F4A /* Preview Content */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | CAFD9B452BB234B800B35F4A /* Preview Assets.xcassets */, 80 | ); 81 | path = "Preview Content"; 82 | sourceTree = ""; 83 | }; 84 | CAFD9B682BB234C600B35F4A /* Frameworks */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | ); 88 | name = Frameworks; 89 | sourceTree = ""; 90 | }; 91 | /* End PBXGroup section */ 92 | 93 | /* Begin PBXNativeTarget section */ 94 | CAFD9B3A2BB234B700B35F4A /* SwiftDependencies */ = { 95 | isa = PBXNativeTarget; 96 | buildConfigurationList = CAFD9B5F2BB234B900B35F4A /* Build configuration list for PBXNativeTarget "SwiftDependencies" */; 97 | buildPhases = ( 98 | CAFD9B372BB234B700B35F4A /* Sources */, 99 | CAFD9B382BB234B700B35F4A /* Frameworks */, 100 | CAFD9B392BB234B700B35F4A /* Resources */, 101 | ); 102 | buildRules = ( 103 | ); 104 | dependencies = ( 105 | ); 106 | name = SwiftDependencies; 107 | packageProductDependencies = ( 108 | CAFD9B692BB234C600B35F4A /* SharedDependencies */, 109 | CAFD9B6C2BB234FD00B35F4A /* Dependencies */, 110 | ); 111 | productName = SwiftDependencies; 112 | productReference = CAFD9B3B2BB234B700B35F4A /* SwiftDependencies.app */; 113 | productType = "com.apple.product-type.application"; 114 | }; 115 | /* End PBXNativeTarget section */ 116 | 117 | /* Begin PBXProject section */ 118 | CAFD9B332BB234B700B35F4A /* Project object */ = { 119 | isa = PBXProject; 120 | attributes = { 121 | BuildIndependentTargetsInParallel = 1; 122 | LastSwiftUpdateCheck = 1530; 123 | LastUpgradeCheck = 1530; 124 | TargetAttributes = { 125 | CAFD9B3A2BB234B700B35F4A = { 126 | CreatedOnToolsVersion = 15.3; 127 | }; 128 | }; 129 | }; 130 | buildConfigurationList = CAFD9B362BB234B700B35F4A /* Build configuration list for PBXProject "SwiftDependencies" */; 131 | compatibilityVersion = "Xcode 14.0"; 132 | developmentRegion = en; 133 | hasScannedForEncodings = 0; 134 | knownRegions = ( 135 | en, 136 | Base, 137 | ); 138 | mainGroup = CAFD9B322BB234B700B35F4A; 139 | packageReferences = ( 140 | CAFD9B6B2BB234FD00B35F4A /* XCRemoteSwiftPackageReference "swift-dependencies" */, 141 | ); 142 | productRefGroup = CAFD9B3C2BB234B700B35F4A /* Products */; 143 | projectDirPath = ""; 144 | projectRoot = ""; 145 | targets = ( 146 | CAFD9B3A2BB234B700B35F4A /* SwiftDependencies */, 147 | ); 148 | }; 149 | /* End PBXProject section */ 150 | 151 | /* Begin PBXResourcesBuildPhase section */ 152 | CAFD9B392BB234B700B35F4A /* Resources */ = { 153 | isa = PBXResourcesBuildPhase; 154 | buildActionMask = 2147483647; 155 | files = ( 156 | CAFD9B462BB234B800B35F4A /* Preview Assets.xcassets in Resources */, 157 | CAFD9B432BB234B800B35F4A /* Assets.xcassets in Resources */, 158 | ); 159 | runOnlyForDeploymentPostprocessing = 0; 160 | }; 161 | /* End PBXResourcesBuildPhase section */ 162 | 163 | /* Begin PBXSourcesBuildPhase section */ 164 | CAFD9B372BB234B700B35F4A /* Sources */ = { 165 | isa = PBXSourcesBuildPhase; 166 | buildActionMask = 2147483647; 167 | files = ( 168 | CAFD9B732BB2375800B35F4A /* Dependencies.swift in Sources */, 169 | CAFD9B412BB234B700B35F4A /* AppFeature.swift in Sources */, 170 | CAFD9B752BB23AD800B35F4A /* AuthenticatedFeature.swift in Sources */, 171 | CAFD9B3F2BB234B700B35F4A /* App.swift in Sources */, 172 | CAFD9B6F2BB2367800B35F4A /* LoggedOutFeature.swift in Sources */, 173 | ); 174 | runOnlyForDeploymentPostprocessing = 0; 175 | }; 176 | /* End PBXSourcesBuildPhase section */ 177 | 178 | /* Begin XCBuildConfiguration section */ 179 | CAFD9B5D2BB234B900B35F4A /* Debug */ = { 180 | isa = XCBuildConfiguration; 181 | buildSettings = { 182 | ALWAYS_SEARCH_USER_PATHS = NO; 183 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 184 | CLANG_ANALYZER_NONNULL = YES; 185 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 186 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 187 | CLANG_ENABLE_MODULES = YES; 188 | CLANG_ENABLE_OBJC_ARC = YES; 189 | CLANG_ENABLE_OBJC_WEAK = YES; 190 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 191 | CLANG_WARN_BOOL_CONVERSION = YES; 192 | CLANG_WARN_COMMA = YES; 193 | CLANG_WARN_CONSTANT_CONVERSION = YES; 194 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 195 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 196 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 197 | CLANG_WARN_EMPTY_BODY = YES; 198 | CLANG_WARN_ENUM_CONVERSION = YES; 199 | CLANG_WARN_INFINITE_RECURSION = YES; 200 | CLANG_WARN_INT_CONVERSION = YES; 201 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 202 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 203 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 204 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 205 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 206 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 207 | CLANG_WARN_STRICT_PROTOTYPES = YES; 208 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 209 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 210 | CLANG_WARN_UNREACHABLE_CODE = YES; 211 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 212 | COPY_PHASE_STRIP = NO; 213 | DEBUG_INFORMATION_FORMAT = dwarf; 214 | ENABLE_STRICT_OBJC_MSGSEND = YES; 215 | ENABLE_TESTABILITY = YES; 216 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 217 | GCC_C_LANGUAGE_STANDARD = gnu17; 218 | GCC_DYNAMIC_NO_PIC = NO; 219 | GCC_NO_COMMON_BLOCKS = YES; 220 | GCC_OPTIMIZATION_LEVEL = 0; 221 | GCC_PREPROCESSOR_DEFINITIONS = ( 222 | "DEBUG=1", 223 | "$(inherited)", 224 | ); 225 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 226 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 227 | GCC_WARN_UNDECLARED_SELECTOR = YES; 228 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 229 | GCC_WARN_UNUSED_FUNCTION = YES; 230 | GCC_WARN_UNUSED_VARIABLE = YES; 231 | IPHONEOS_DEPLOYMENT_TARGET = 17.4; 232 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 233 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 234 | MTL_FAST_MATH = YES; 235 | ONLY_ACTIVE_ARCH = YES; 236 | SDKROOT = iphoneos; 237 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; 238 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 239 | SWIFT_STRICT_CONCURRENCY = complete; 240 | }; 241 | name = Debug; 242 | }; 243 | CAFD9B5E2BB234B900B35F4A /* Release */ = { 244 | isa = XCBuildConfiguration; 245 | buildSettings = { 246 | ALWAYS_SEARCH_USER_PATHS = NO; 247 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 248 | CLANG_ANALYZER_NONNULL = YES; 249 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 250 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 251 | CLANG_ENABLE_MODULES = YES; 252 | CLANG_ENABLE_OBJC_ARC = YES; 253 | CLANG_ENABLE_OBJC_WEAK = YES; 254 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 255 | CLANG_WARN_BOOL_CONVERSION = YES; 256 | CLANG_WARN_COMMA = YES; 257 | CLANG_WARN_CONSTANT_CONVERSION = YES; 258 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 259 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 260 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 261 | CLANG_WARN_EMPTY_BODY = YES; 262 | CLANG_WARN_ENUM_CONVERSION = YES; 263 | CLANG_WARN_INFINITE_RECURSION = YES; 264 | CLANG_WARN_INT_CONVERSION = YES; 265 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 266 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 267 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 268 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 269 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 270 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 271 | CLANG_WARN_STRICT_PROTOTYPES = YES; 272 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 273 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 274 | CLANG_WARN_UNREACHABLE_CODE = YES; 275 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 276 | COPY_PHASE_STRIP = NO; 277 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 278 | ENABLE_NS_ASSERTIONS = NO; 279 | ENABLE_STRICT_OBJC_MSGSEND = YES; 280 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 281 | GCC_C_LANGUAGE_STANDARD = gnu17; 282 | GCC_NO_COMMON_BLOCKS = YES; 283 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 284 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 285 | GCC_WARN_UNDECLARED_SELECTOR = YES; 286 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 287 | GCC_WARN_UNUSED_FUNCTION = YES; 288 | GCC_WARN_UNUSED_VARIABLE = YES; 289 | IPHONEOS_DEPLOYMENT_TARGET = 17.4; 290 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 291 | MTL_ENABLE_DEBUG_INFO = NO; 292 | MTL_FAST_MATH = YES; 293 | SDKROOT = iphoneos; 294 | SWIFT_COMPILATION_MODE = wholemodule; 295 | SWIFT_STRICT_CONCURRENCY = complete; 296 | VALIDATE_PRODUCT = YES; 297 | }; 298 | name = Release; 299 | }; 300 | CAFD9B602BB234B900B35F4A /* Debug */ = { 301 | isa = XCBuildConfiguration; 302 | buildSettings = { 303 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 304 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 305 | CODE_SIGN_STYLE = Automatic; 306 | CURRENT_PROJECT_VERSION = 1; 307 | DEVELOPMENT_ASSET_PATHS = "\"SwiftDependencies/Preview Content\""; 308 | ENABLE_PREVIEWS = YES; 309 | GENERATE_INFOPLIST_FILE = YES; 310 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 311 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 312 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 313 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 314 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 315 | IPHONEOS_DEPLOYMENT_TARGET = 17.2; 316 | LD_RUNPATH_SEARCH_PATHS = ( 317 | "$(inherited)", 318 | "@executable_path/Frameworks", 319 | ); 320 | MACOSX_DEPLOYMENT_TARGET = 14.2; 321 | MARKETING_VERSION = 1.0; 322 | PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.SwiftDependencies; 323 | PRODUCT_NAME = "$(TARGET_NAME)"; 324 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; 325 | SUPPORTS_MACCATALYST = NO; 326 | SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; 327 | SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; 328 | SWIFT_EMIT_LOC_STRINGS = YES; 329 | SWIFT_VERSION = 5.0; 330 | TARGETED_DEVICE_FAMILY = "1,2"; 331 | }; 332 | name = Debug; 333 | }; 334 | CAFD9B612BB234B900B35F4A /* Release */ = { 335 | isa = XCBuildConfiguration; 336 | buildSettings = { 337 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 338 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 339 | CODE_SIGN_STYLE = Automatic; 340 | CURRENT_PROJECT_VERSION = 1; 341 | DEVELOPMENT_ASSET_PATHS = "\"SwiftDependencies/Preview Content\""; 342 | ENABLE_PREVIEWS = YES; 343 | GENERATE_INFOPLIST_FILE = YES; 344 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 345 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 346 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 347 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 348 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 349 | IPHONEOS_DEPLOYMENT_TARGET = 17.2; 350 | LD_RUNPATH_SEARCH_PATHS = ( 351 | "$(inherited)", 352 | "@executable_path/Frameworks", 353 | ); 354 | MACOSX_DEPLOYMENT_TARGET = 14.2; 355 | MARKETING_VERSION = 1.0; 356 | PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.SwiftDependencies; 357 | PRODUCT_NAME = "$(TARGET_NAME)"; 358 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; 359 | SUPPORTS_MACCATALYST = NO; 360 | SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; 361 | SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; 362 | SWIFT_EMIT_LOC_STRINGS = YES; 363 | SWIFT_VERSION = 5.0; 364 | TARGETED_DEVICE_FAMILY = "1,2"; 365 | }; 366 | name = Release; 367 | }; 368 | /* End XCBuildConfiguration section */ 369 | 370 | /* Begin XCConfigurationList section */ 371 | CAFD9B362BB234B700B35F4A /* Build configuration list for PBXProject "SwiftDependencies" */ = { 372 | isa = XCConfigurationList; 373 | buildConfigurations = ( 374 | CAFD9B5D2BB234B900B35F4A /* Debug */, 375 | CAFD9B5E2BB234B900B35F4A /* Release */, 376 | ); 377 | defaultConfigurationIsVisible = 0; 378 | defaultConfigurationName = Release; 379 | }; 380 | CAFD9B5F2BB234B900B35F4A /* Build configuration list for PBXNativeTarget "SwiftDependencies" */ = { 381 | isa = XCConfigurationList; 382 | buildConfigurations = ( 383 | CAFD9B602BB234B900B35F4A /* Debug */, 384 | CAFD9B612BB234B900B35F4A /* Release */, 385 | ); 386 | defaultConfigurationIsVisible = 0; 387 | defaultConfigurationName = Release; 388 | }; 389 | /* End XCConfigurationList section */ 390 | 391 | /* Begin XCRemoteSwiftPackageReference section */ 392 | CAFD9B6B2BB234FD00B35F4A /* XCRemoteSwiftPackageReference "swift-dependencies" */ = { 393 | isa = XCRemoteSwiftPackageReference; 394 | repositoryURL = "https://github.com/pointfreeco/swift-dependencies.git"; 395 | requirement = { 396 | kind = upToNextMajorVersion; 397 | minimumVersion = 1.2.2; 398 | }; 399 | }; 400 | /* End XCRemoteSwiftPackageReference section */ 401 | 402 | /* Begin XCSwiftPackageProductDependency section */ 403 | CAFD9B692BB234C600B35F4A /* SharedDependencies */ = { 404 | isa = XCSwiftPackageProductDependency; 405 | productName = SharedDependencies; 406 | }; 407 | CAFD9B6C2BB234FD00B35F4A /* Dependencies */ = { 408 | isa = XCSwiftPackageProductDependency; 409 | package = CAFD9B6B2BB234FD00B35F4A /* XCRemoteSwiftPackageReference "swift-dependencies" */; 410 | productName = Dependencies; 411 | }; 412 | /* End XCSwiftPackageProductDependency section */ 413 | }; 414 | rootObject = CAFD9B332BB234B700B35F4A /* Project object */; 415 | } 416 | -------------------------------------------------------------------------------- /EnvironmentDependencies/EnvironmentDependencies.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 60; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | A0107ABF2BA45EAC00D3A35B /* EnvironmentDependenciesApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0107ABE2BA45EAC00D3A35B /* EnvironmentDependenciesApp.swift */; }; 11 | A0107AC12BA45EAC00D3A35B /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0107AC02BA45EAC00D3A35B /* ContentView.swift */; }; 12 | A0107AC32BA45EB100D3A35B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A0107AC22BA45EB100D3A35B /* Assets.xcassets */; }; 13 | A0107AC72BA45EB100D3A35B /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A0107AC62BA45EB100D3A35B /* Preview Assets.xcassets */; }; 14 | A0107AD02BA466EA00D3A35B /* Model.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0107ACF2BA466E900D3A35B /* Model.swift */; }; 15 | A0107AD32BA46CB000D3A35B /* SharedDependencies in Frameworks */ = {isa = PBXBuildFile; productRef = A0107AD22BA46CB000D3A35B /* SharedDependencies */; }; 16 | A0C7F3E02BAEEC4500204047 /* EnvironmentSetup.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0C7F3DF2BAEEC4500204047 /* EnvironmentSetup.swift */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | A0107ABB2BA45EAC00D3A35B /* EnvironmentDependencies.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EnvironmentDependencies.app; sourceTree = BUILT_PRODUCTS_DIR; }; 21 | A0107ABE2BA45EAC00D3A35B /* EnvironmentDependenciesApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnvironmentDependenciesApp.swift; sourceTree = ""; }; 22 | A0107AC02BA45EAC00D3A35B /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 23 | A0107AC22BA45EB100D3A35B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 24 | A0107AC42BA45EB100D3A35B /* EnvironmentDependencies.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = EnvironmentDependencies.entitlements; sourceTree = ""; }; 25 | A0107AC62BA45EB100D3A35B /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 26 | A0107ACF2BA466E900D3A35B /* Model.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Model.swift; sourceTree = ""; }; 27 | A0C7F3DF2BAEEC4500204047 /* EnvironmentSetup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnvironmentSetup.swift; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | A0107AB82BA45EAC00D3A35B /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | A0107AD32BA46CB000D3A35B /* SharedDependencies in Frameworks */, 36 | ); 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXFrameworksBuildPhase section */ 40 | 41 | /* Begin PBXGroup section */ 42 | A0107AB22BA45EAC00D3A35B = { 43 | isa = PBXGroup; 44 | children = ( 45 | A0107ABD2BA45EAC00D3A35B /* EnvironmentDependencies */, 46 | A0107ABC2BA45EAC00D3A35B /* Products */, 47 | ); 48 | sourceTree = ""; 49 | }; 50 | A0107ABC2BA45EAC00D3A35B /* Products */ = { 51 | isa = PBXGroup; 52 | children = ( 53 | A0107ABB2BA45EAC00D3A35B /* EnvironmentDependencies.app */, 54 | ); 55 | name = Products; 56 | sourceTree = ""; 57 | }; 58 | A0107ABD2BA45EAC00D3A35B /* EnvironmentDependencies */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | A0107ABE2BA45EAC00D3A35B /* EnvironmentDependenciesApp.swift */, 62 | A0107AC02BA45EAC00D3A35B /* ContentView.swift */, 63 | A0107ACF2BA466E900D3A35B /* Model.swift */, 64 | A0C7F3DF2BAEEC4500204047 /* EnvironmentSetup.swift */, 65 | A0107AC22BA45EB100D3A35B /* Assets.xcassets */, 66 | A0107AC42BA45EB100D3A35B /* EnvironmentDependencies.entitlements */, 67 | A0107AC52BA45EB100D3A35B /* Preview Content */, 68 | ); 69 | path = EnvironmentDependencies; 70 | sourceTree = ""; 71 | }; 72 | A0107AC52BA45EB100D3A35B /* Preview Content */ = { 73 | isa = PBXGroup; 74 | children = ( 75 | A0107AC62BA45EB100D3A35B /* Preview Assets.xcassets */, 76 | ); 77 | path = "Preview Content"; 78 | sourceTree = ""; 79 | }; 80 | /* End PBXGroup section */ 81 | 82 | /* Begin PBXNativeTarget section */ 83 | A0107ABA2BA45EAC00D3A35B /* EnvironmentDependencies */ = { 84 | isa = PBXNativeTarget; 85 | buildConfigurationList = A0107ACA2BA45EB100D3A35B /* Build configuration list for PBXNativeTarget "EnvironmentDependencies" */; 86 | buildPhases = ( 87 | A0107AB72BA45EAC00D3A35B /* Sources */, 88 | A0107AB82BA45EAC00D3A35B /* Frameworks */, 89 | A0107AB92BA45EAC00D3A35B /* Resources */, 90 | ); 91 | buildRules = ( 92 | ); 93 | dependencies = ( 94 | ); 95 | name = EnvironmentDependencies; 96 | packageProductDependencies = ( 97 | A0107AD22BA46CB000D3A35B /* SharedDependencies */, 98 | ); 99 | productName = EnvironmentDependencies; 100 | productReference = A0107ABB2BA45EAC00D3A35B /* EnvironmentDependencies.app */; 101 | productType = "com.apple.product-type.application"; 102 | }; 103 | /* End PBXNativeTarget section */ 104 | 105 | /* Begin PBXProject section */ 106 | A0107AB32BA45EAC00D3A35B /* Project object */ = { 107 | isa = PBXProject; 108 | attributes = { 109 | BuildIndependentTargetsInParallel = 1; 110 | LastSwiftUpdateCheck = 1520; 111 | LastUpgradeCheck = 1530; 112 | TargetAttributes = { 113 | A0107ABA2BA45EAC00D3A35B = { 114 | CreatedOnToolsVersion = 15.2; 115 | }; 116 | }; 117 | }; 118 | buildConfigurationList = A0107AB62BA45EAC00D3A35B /* Build configuration list for PBXProject "EnvironmentDependencies" */; 119 | compatibilityVersion = "Xcode 14.0"; 120 | developmentRegion = en; 121 | hasScannedForEncodings = 0; 122 | knownRegions = ( 123 | en, 124 | Base, 125 | ); 126 | mainGroup = A0107AB22BA45EAC00D3A35B; 127 | packageReferences = ( 128 | A0107AD12BA46CB000D3A35B /* XCLocalSwiftPackageReference "../SharedDependencies" */, 129 | ); 130 | productRefGroup = A0107ABC2BA45EAC00D3A35B /* Products */; 131 | projectDirPath = ""; 132 | projectRoot = ""; 133 | targets = ( 134 | A0107ABA2BA45EAC00D3A35B /* EnvironmentDependencies */, 135 | ); 136 | }; 137 | /* End PBXProject section */ 138 | 139 | /* Begin PBXResourcesBuildPhase section */ 140 | A0107AB92BA45EAC00D3A35B /* Resources */ = { 141 | isa = PBXResourcesBuildPhase; 142 | buildActionMask = 2147483647; 143 | files = ( 144 | A0107AC72BA45EB100D3A35B /* Preview Assets.xcassets in Resources */, 145 | A0107AC32BA45EB100D3A35B /* Assets.xcassets in Resources */, 146 | ); 147 | runOnlyForDeploymentPostprocessing = 0; 148 | }; 149 | /* End PBXResourcesBuildPhase section */ 150 | 151 | /* Begin PBXSourcesBuildPhase section */ 152 | A0107AB72BA45EAC00D3A35B /* Sources */ = { 153 | isa = PBXSourcesBuildPhase; 154 | buildActionMask = 2147483647; 155 | files = ( 156 | A0107AD02BA466EA00D3A35B /* Model.swift in Sources */, 157 | A0107AC12BA45EAC00D3A35B /* ContentView.swift in Sources */, 158 | A0107ABF2BA45EAC00D3A35B /* EnvironmentDependenciesApp.swift in Sources */, 159 | A0C7F3E02BAEEC4500204047 /* EnvironmentSetup.swift in Sources */, 160 | ); 161 | runOnlyForDeploymentPostprocessing = 0; 162 | }; 163 | /* End PBXSourcesBuildPhase section */ 164 | 165 | /* Begin XCBuildConfiguration section */ 166 | A0107AC82BA45EB100D3A35B /* Debug */ = { 167 | isa = XCBuildConfiguration; 168 | buildSettings = { 169 | ALWAYS_SEARCH_USER_PATHS = NO; 170 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 171 | CLANG_ANALYZER_NONNULL = YES; 172 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 173 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 174 | CLANG_ENABLE_MODULES = YES; 175 | CLANG_ENABLE_OBJC_ARC = YES; 176 | CLANG_ENABLE_OBJC_WEAK = YES; 177 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 178 | CLANG_WARN_BOOL_CONVERSION = YES; 179 | CLANG_WARN_COMMA = YES; 180 | CLANG_WARN_CONSTANT_CONVERSION = YES; 181 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 182 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 183 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 184 | CLANG_WARN_EMPTY_BODY = YES; 185 | CLANG_WARN_ENUM_CONVERSION = YES; 186 | CLANG_WARN_INFINITE_RECURSION = YES; 187 | CLANG_WARN_INT_CONVERSION = YES; 188 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 189 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 190 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 191 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 192 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 193 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 194 | CLANG_WARN_STRICT_PROTOTYPES = YES; 195 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 196 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 197 | CLANG_WARN_UNREACHABLE_CODE = YES; 198 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 199 | COPY_PHASE_STRIP = NO; 200 | DEAD_CODE_STRIPPING = YES; 201 | DEBUG_INFORMATION_FORMAT = dwarf; 202 | ENABLE_STRICT_OBJC_MSGSEND = YES; 203 | ENABLE_TESTABILITY = YES; 204 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 205 | GCC_C_LANGUAGE_STANDARD = gnu17; 206 | GCC_DYNAMIC_NO_PIC = NO; 207 | GCC_NO_COMMON_BLOCKS = YES; 208 | GCC_OPTIMIZATION_LEVEL = 0; 209 | GCC_PREPROCESSOR_DEFINITIONS = ( 210 | "DEBUG=1", 211 | "$(inherited)", 212 | ); 213 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 214 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 215 | GCC_WARN_UNDECLARED_SELECTOR = YES; 216 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 217 | GCC_WARN_UNUSED_FUNCTION = YES; 218 | GCC_WARN_UNUSED_VARIABLE = YES; 219 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 220 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 221 | MTL_FAST_MATH = YES; 222 | ONLY_ACTIVE_ARCH = YES; 223 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; 224 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 225 | SWIFT_STRICT_CONCURRENCY = complete; 226 | }; 227 | name = Debug; 228 | }; 229 | A0107AC92BA45EB100D3A35B /* Release */ = { 230 | isa = XCBuildConfiguration; 231 | buildSettings = { 232 | ALWAYS_SEARCH_USER_PATHS = NO; 233 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 234 | CLANG_ANALYZER_NONNULL = YES; 235 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 236 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 237 | CLANG_ENABLE_MODULES = YES; 238 | CLANG_ENABLE_OBJC_ARC = YES; 239 | CLANG_ENABLE_OBJC_WEAK = YES; 240 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 241 | CLANG_WARN_BOOL_CONVERSION = YES; 242 | CLANG_WARN_COMMA = YES; 243 | CLANG_WARN_CONSTANT_CONVERSION = YES; 244 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 245 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 246 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 247 | CLANG_WARN_EMPTY_BODY = YES; 248 | CLANG_WARN_ENUM_CONVERSION = YES; 249 | CLANG_WARN_INFINITE_RECURSION = YES; 250 | CLANG_WARN_INT_CONVERSION = YES; 251 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 252 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 253 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 254 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 255 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 256 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 257 | CLANG_WARN_STRICT_PROTOTYPES = YES; 258 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 259 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 260 | CLANG_WARN_UNREACHABLE_CODE = YES; 261 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 262 | COPY_PHASE_STRIP = NO; 263 | DEAD_CODE_STRIPPING = YES; 264 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 265 | ENABLE_NS_ASSERTIONS = NO; 266 | ENABLE_STRICT_OBJC_MSGSEND = YES; 267 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 268 | GCC_C_LANGUAGE_STANDARD = gnu17; 269 | GCC_NO_COMMON_BLOCKS = YES; 270 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 271 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 272 | GCC_WARN_UNDECLARED_SELECTOR = YES; 273 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 274 | GCC_WARN_UNUSED_FUNCTION = YES; 275 | GCC_WARN_UNUSED_VARIABLE = YES; 276 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 277 | MTL_ENABLE_DEBUG_INFO = NO; 278 | MTL_FAST_MATH = YES; 279 | SWIFT_COMPILATION_MODE = wholemodule; 280 | SWIFT_STRICT_CONCURRENCY = complete; 281 | }; 282 | name = Release; 283 | }; 284 | A0107ACB2BA45EB100D3A35B /* Debug */ = { 285 | isa = XCBuildConfiguration; 286 | buildSettings = { 287 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 288 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 289 | CODE_SIGN_ENTITLEMENTS = EnvironmentDependencies/EnvironmentDependencies.entitlements; 290 | CODE_SIGN_STYLE = Automatic; 291 | CURRENT_PROJECT_VERSION = 1; 292 | DEAD_CODE_STRIPPING = YES; 293 | DEVELOPMENT_ASSET_PATHS = "\"EnvironmentDependencies/Preview Content\""; 294 | DEVELOPMENT_TEAM = 79L7M968L6; 295 | ENABLE_HARDENED_RUNTIME = YES; 296 | ENABLE_PREVIEWS = YES; 297 | GENERATE_INFOPLIST_FILE = YES; 298 | "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; 299 | "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; 300 | "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; 301 | "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; 302 | "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; 303 | "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; 304 | "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; 305 | "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; 306 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 307 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 308 | IPHONEOS_DEPLOYMENT_TARGET = 17.2; 309 | LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; 310 | "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; 311 | MACOSX_DEPLOYMENT_TARGET = 14.2; 312 | MARKETING_VERSION = 1.0; 313 | PRODUCT_BUNDLE_IDENTIFIER = dev.lucasvandongen.EnvironmentDependencies; 314 | PRODUCT_NAME = "$(TARGET_NAME)"; 315 | SDKROOT = auto; 316 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; 317 | SWIFT_EMIT_LOC_STRINGS = YES; 318 | SWIFT_STRICT_CONCURRENCY = complete; 319 | SWIFT_VERSION = 5.0; 320 | TARGETED_DEVICE_FAMILY = "1,2"; 321 | }; 322 | name = Debug; 323 | }; 324 | A0107ACC2BA45EB100D3A35B /* Release */ = { 325 | isa = XCBuildConfiguration; 326 | buildSettings = { 327 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 328 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 329 | CODE_SIGN_ENTITLEMENTS = EnvironmentDependencies/EnvironmentDependencies.entitlements; 330 | CODE_SIGN_STYLE = Automatic; 331 | CURRENT_PROJECT_VERSION = 1; 332 | DEAD_CODE_STRIPPING = YES; 333 | DEVELOPMENT_ASSET_PATHS = "\"EnvironmentDependencies/Preview Content\""; 334 | DEVELOPMENT_TEAM = 79L7M968L6; 335 | ENABLE_HARDENED_RUNTIME = YES; 336 | ENABLE_PREVIEWS = YES; 337 | GENERATE_INFOPLIST_FILE = YES; 338 | "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; 339 | "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; 340 | "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; 341 | "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; 342 | "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; 343 | "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; 344 | "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; 345 | "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; 346 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 347 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 348 | IPHONEOS_DEPLOYMENT_TARGET = 17.2; 349 | LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; 350 | "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; 351 | MACOSX_DEPLOYMENT_TARGET = 14.2; 352 | MARKETING_VERSION = 1.0; 353 | PRODUCT_BUNDLE_IDENTIFIER = dev.lucasvandongen.EnvironmentDependencies; 354 | PRODUCT_NAME = "$(TARGET_NAME)"; 355 | SDKROOT = auto; 356 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; 357 | SWIFT_EMIT_LOC_STRINGS = YES; 358 | SWIFT_STRICT_CONCURRENCY = complete; 359 | SWIFT_VERSION = 5.0; 360 | TARGETED_DEVICE_FAMILY = "1,2"; 361 | }; 362 | name = Release; 363 | }; 364 | /* End XCBuildConfiguration section */ 365 | 366 | /* Begin XCConfigurationList section */ 367 | A0107AB62BA45EAC00D3A35B /* Build configuration list for PBXProject "EnvironmentDependencies" */ = { 368 | isa = XCConfigurationList; 369 | buildConfigurations = ( 370 | A0107AC82BA45EB100D3A35B /* Debug */, 371 | A0107AC92BA45EB100D3A35B /* Release */, 372 | ); 373 | defaultConfigurationIsVisible = 0; 374 | defaultConfigurationName = Release; 375 | }; 376 | A0107ACA2BA45EB100D3A35B /* Build configuration list for PBXNativeTarget "EnvironmentDependencies" */ = { 377 | isa = XCConfigurationList; 378 | buildConfigurations = ( 379 | A0107ACB2BA45EB100D3A35B /* Debug */, 380 | A0107ACC2BA45EB100D3A35B /* Release */, 381 | ); 382 | defaultConfigurationIsVisible = 0; 383 | defaultConfigurationName = Release; 384 | }; 385 | /* End XCConfigurationList section */ 386 | 387 | /* Begin XCLocalSwiftPackageReference section */ 388 | A0107AD12BA46CB000D3A35B /* XCLocalSwiftPackageReference "../SharedDependencies" */ = { 389 | isa = XCLocalSwiftPackageReference; 390 | relativePath = ../SharedDependencies; 391 | }; 392 | /* End XCLocalSwiftPackageReference section */ 393 | 394 | /* Begin XCSwiftPackageProductDependency section */ 395 | A0107AD22BA46CB000D3A35B /* SharedDependencies */ = { 396 | isa = XCSwiftPackageProductDependency; 397 | productName = SharedDependencies; 398 | }; 399 | /* End XCSwiftPackageProductDependency section */ 400 | }; 401 | rootObject = A0107AB32BA45EAC00D3A35B /* Project object */; 402 | } 403 | -------------------------------------------------------------------------------- /PassedDependencies/PassedDependencies.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 60; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | A07AFD4A2B989AEA004954C9 /* PassedDependenciesApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A07AFD492B989AEA004954C9 /* PassedDependenciesApp.swift */; }; 11 | A07AFD4C2B989AEA004954C9 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A07AFD4B2B989AEA004954C9 /* ContentView.swift */; }; 12 | A07AFD4E2B989AED004954C9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A07AFD4D2B989AED004954C9 /* Assets.xcassets */; }; 13 | A07AFD522B989AED004954C9 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A07AFD512B989AED004954C9 /* Preview Assets.xcassets */; }; 14 | A07AFD592B989AFF004954C9 /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = A07AFD582B989AFF004954C9 /* Container.swift */; }; 15 | A07AFD5C2B989B4F004954C9 /* SharedDependencies in Frameworks */ = {isa = PBXBuildFile; productRef = A07AFD5B2B989B4F004954C9 /* SharedDependencies */; }; 16 | A07AFD5E2B989FD0004954C9 /* Model.swift in Sources */ = {isa = PBXBuildFile; fileRef = A07AFD5D2B989FD0004954C9 /* Model.swift */; }; 17 | A0C7F3DE2BAEE28200204047 /* AuthenticatedFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0C7F3DD2BAEE28200204047 /* AuthenticatedFactory.swift */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXFileReference section */ 21 | A07AFD462B989AEA004954C9 /* PassedDependencies.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PassedDependencies.app; sourceTree = BUILT_PRODUCTS_DIR; }; 22 | A07AFD492B989AEA004954C9 /* PassedDependenciesApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PassedDependenciesApp.swift; sourceTree = ""; }; 23 | A07AFD4B2B989AEA004954C9 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 24 | A07AFD4D2B989AED004954C9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 25 | A07AFD4F2B989AED004954C9 /* PassedDependencies.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = PassedDependencies.entitlements; sourceTree = ""; }; 26 | A07AFD512B989AED004954C9 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 27 | A07AFD582B989AFF004954C9 /* Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = ""; }; 28 | A07AFD5D2B989FD0004954C9 /* Model.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Model.swift; sourceTree = ""; }; 29 | A0C7F3DD2BAEE28200204047 /* AuthenticatedFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticatedFactory.swift; sourceTree = ""; }; 30 | /* End PBXFileReference section */ 31 | 32 | /* Begin PBXFrameworksBuildPhase section */ 33 | A07AFD432B989AEA004954C9 /* Frameworks */ = { 34 | isa = PBXFrameworksBuildPhase; 35 | buildActionMask = 2147483647; 36 | files = ( 37 | A07AFD5C2B989B4F004954C9 /* SharedDependencies in Frameworks */, 38 | ); 39 | runOnlyForDeploymentPostprocessing = 0; 40 | }; 41 | /* End PBXFrameworksBuildPhase section */ 42 | 43 | /* Begin PBXGroup section */ 44 | A07AFD3D2B989AEA004954C9 = { 45 | isa = PBXGroup; 46 | children = ( 47 | A07AFD482B989AEA004954C9 /* PassedDependencies */, 48 | A07AFD472B989AEA004954C9 /* Products */, 49 | ); 50 | sourceTree = ""; 51 | }; 52 | A07AFD472B989AEA004954C9 /* Products */ = { 53 | isa = PBXGroup; 54 | children = ( 55 | A07AFD462B989AEA004954C9 /* PassedDependencies.app */, 56 | ); 57 | name = Products; 58 | sourceTree = ""; 59 | }; 60 | A07AFD482B989AEA004954C9 /* PassedDependencies */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | A0C7F3DC2BAEE27100204047 /* Factories */, 64 | A07AFD492B989AEA004954C9 /* PassedDependenciesApp.swift */, 65 | A07AFD4B2B989AEA004954C9 /* ContentView.swift */, 66 | A07AFD4D2B989AED004954C9 /* Assets.xcassets */, 67 | A07AFD4F2B989AED004954C9 /* PassedDependencies.entitlements */, 68 | A07AFD502B989AED004954C9 /* Preview Content */, 69 | A07AFD582B989AFF004954C9 /* Container.swift */, 70 | A07AFD5D2B989FD0004954C9 /* Model.swift */, 71 | ); 72 | path = PassedDependencies; 73 | sourceTree = ""; 74 | }; 75 | A07AFD502B989AED004954C9 /* Preview Content */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | A07AFD512B989AED004954C9 /* Preview Assets.xcassets */, 79 | ); 80 | path = "Preview Content"; 81 | sourceTree = ""; 82 | }; 83 | A0C7F3DC2BAEE27100204047 /* Factories */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | A0C7F3DD2BAEE28200204047 /* AuthenticatedFactory.swift */, 87 | ); 88 | path = Factories; 89 | sourceTree = ""; 90 | }; 91 | /* End PBXGroup section */ 92 | 93 | /* Begin PBXNativeTarget section */ 94 | A07AFD452B989AEA004954C9 /* PassedDependencies */ = { 95 | isa = PBXNativeTarget; 96 | buildConfigurationList = A07AFD552B989AED004954C9 /* Build configuration list for PBXNativeTarget "PassedDependencies" */; 97 | buildPhases = ( 98 | A07AFD422B989AEA004954C9 /* Sources */, 99 | A07AFD432B989AEA004954C9 /* Frameworks */, 100 | A07AFD442B989AEA004954C9 /* Resources */, 101 | ); 102 | buildRules = ( 103 | ); 104 | dependencies = ( 105 | ); 106 | name = PassedDependencies; 107 | packageProductDependencies = ( 108 | A07AFD5B2B989B4F004954C9 /* SharedDependencies */, 109 | ); 110 | productName = PassedDependencies; 111 | productReference = A07AFD462B989AEA004954C9 /* PassedDependencies.app */; 112 | productType = "com.apple.product-type.application"; 113 | }; 114 | /* End PBXNativeTarget section */ 115 | 116 | /* Begin PBXProject section */ 117 | A07AFD3E2B989AEA004954C9 /* Project object */ = { 118 | isa = PBXProject; 119 | attributes = { 120 | BuildIndependentTargetsInParallel = 1; 121 | LastSwiftUpdateCheck = 1520; 122 | LastUpgradeCheck = 1520; 123 | TargetAttributes = { 124 | A07AFD452B989AEA004954C9 = { 125 | CreatedOnToolsVersion = 15.2; 126 | }; 127 | }; 128 | }; 129 | buildConfigurationList = A07AFD412B989AEA004954C9 /* Build configuration list for PBXProject "PassedDependencies" */; 130 | compatibilityVersion = "Xcode 14.0"; 131 | developmentRegion = en; 132 | hasScannedForEncodings = 0; 133 | knownRegions = ( 134 | en, 135 | Base, 136 | ); 137 | mainGroup = A07AFD3D2B989AEA004954C9; 138 | packageReferences = ( 139 | A07AFD5A2B989B4F004954C9 /* XCLocalSwiftPackageReference "../SharedDependencies" */, 140 | ); 141 | productRefGroup = A07AFD472B989AEA004954C9 /* Products */; 142 | projectDirPath = ""; 143 | projectRoot = ""; 144 | targets = ( 145 | A07AFD452B989AEA004954C9 /* PassedDependencies */, 146 | ); 147 | }; 148 | /* End PBXProject section */ 149 | 150 | /* Begin PBXResourcesBuildPhase section */ 151 | A07AFD442B989AEA004954C9 /* Resources */ = { 152 | isa = PBXResourcesBuildPhase; 153 | buildActionMask = 2147483647; 154 | files = ( 155 | A07AFD522B989AED004954C9 /* Preview Assets.xcassets in Resources */, 156 | A07AFD4E2B989AED004954C9 /* Assets.xcassets in Resources */, 157 | ); 158 | runOnlyForDeploymentPostprocessing = 0; 159 | }; 160 | /* End PBXResourcesBuildPhase section */ 161 | 162 | /* Begin PBXSourcesBuildPhase section */ 163 | A07AFD422B989AEA004954C9 /* Sources */ = { 164 | isa = PBXSourcesBuildPhase; 165 | buildActionMask = 2147483647; 166 | files = ( 167 | A07AFD4C2B989AEA004954C9 /* ContentView.swift in Sources */, 168 | A0C7F3DE2BAEE28200204047 /* AuthenticatedFactory.swift in Sources */, 169 | A07AFD592B989AFF004954C9 /* Container.swift in Sources */, 170 | A07AFD4A2B989AEA004954C9 /* PassedDependenciesApp.swift in Sources */, 171 | A07AFD5E2B989FD0004954C9 /* Model.swift in Sources */, 172 | ); 173 | runOnlyForDeploymentPostprocessing = 0; 174 | }; 175 | /* End PBXSourcesBuildPhase section */ 176 | 177 | /* Begin XCBuildConfiguration section */ 178 | A07AFD532B989AED004954C9 /* Debug */ = { 179 | isa = XCBuildConfiguration; 180 | buildSettings = { 181 | ALWAYS_SEARCH_USER_PATHS = NO; 182 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 183 | CLANG_ANALYZER_NONNULL = YES; 184 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 185 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 186 | CLANG_ENABLE_MODULES = YES; 187 | CLANG_ENABLE_OBJC_ARC = YES; 188 | CLANG_ENABLE_OBJC_WEAK = YES; 189 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 190 | CLANG_WARN_BOOL_CONVERSION = YES; 191 | CLANG_WARN_COMMA = YES; 192 | CLANG_WARN_CONSTANT_CONVERSION = YES; 193 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 194 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 195 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 196 | CLANG_WARN_EMPTY_BODY = YES; 197 | CLANG_WARN_ENUM_CONVERSION = YES; 198 | CLANG_WARN_INFINITE_RECURSION = YES; 199 | CLANG_WARN_INT_CONVERSION = YES; 200 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 201 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 202 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 203 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 204 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 205 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 206 | CLANG_WARN_STRICT_PROTOTYPES = YES; 207 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 208 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 209 | CLANG_WARN_UNREACHABLE_CODE = YES; 210 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 211 | COPY_PHASE_STRIP = NO; 212 | DEBUG_INFORMATION_FORMAT = dwarf; 213 | ENABLE_STRICT_OBJC_MSGSEND = YES; 214 | ENABLE_TESTABILITY = YES; 215 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 216 | GCC_C_LANGUAGE_STANDARD = gnu17; 217 | GCC_DYNAMIC_NO_PIC = NO; 218 | GCC_NO_COMMON_BLOCKS = YES; 219 | GCC_OPTIMIZATION_LEVEL = 0; 220 | GCC_PREPROCESSOR_DEFINITIONS = ( 221 | "DEBUG=1", 222 | "$(inherited)", 223 | ); 224 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 225 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 226 | GCC_WARN_UNDECLARED_SELECTOR = YES; 227 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 228 | GCC_WARN_UNUSED_FUNCTION = YES; 229 | GCC_WARN_UNUSED_VARIABLE = YES; 230 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 231 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 232 | MTL_FAST_MATH = YES; 233 | ONLY_ACTIVE_ARCH = YES; 234 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; 235 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 236 | SWIFT_STRICT_CONCURRENCY = complete; 237 | }; 238 | name = Debug; 239 | }; 240 | A07AFD542B989AED004954C9 /* Release */ = { 241 | isa = XCBuildConfiguration; 242 | buildSettings = { 243 | ALWAYS_SEARCH_USER_PATHS = NO; 244 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 245 | CLANG_ANALYZER_NONNULL = YES; 246 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 247 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 248 | CLANG_ENABLE_MODULES = YES; 249 | CLANG_ENABLE_OBJC_ARC = YES; 250 | CLANG_ENABLE_OBJC_WEAK = YES; 251 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 252 | CLANG_WARN_BOOL_CONVERSION = YES; 253 | CLANG_WARN_COMMA = YES; 254 | CLANG_WARN_CONSTANT_CONVERSION = YES; 255 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 256 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 257 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 258 | CLANG_WARN_EMPTY_BODY = YES; 259 | CLANG_WARN_ENUM_CONVERSION = YES; 260 | CLANG_WARN_INFINITE_RECURSION = YES; 261 | CLANG_WARN_INT_CONVERSION = YES; 262 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 263 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 264 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 265 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 266 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 267 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 268 | CLANG_WARN_STRICT_PROTOTYPES = YES; 269 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 270 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 271 | CLANG_WARN_UNREACHABLE_CODE = YES; 272 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 273 | COPY_PHASE_STRIP = NO; 274 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 275 | ENABLE_NS_ASSERTIONS = NO; 276 | ENABLE_STRICT_OBJC_MSGSEND = YES; 277 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 278 | GCC_C_LANGUAGE_STANDARD = gnu17; 279 | GCC_NO_COMMON_BLOCKS = YES; 280 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 281 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 282 | GCC_WARN_UNDECLARED_SELECTOR = YES; 283 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 284 | GCC_WARN_UNUSED_FUNCTION = YES; 285 | GCC_WARN_UNUSED_VARIABLE = YES; 286 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 287 | MTL_ENABLE_DEBUG_INFO = NO; 288 | MTL_FAST_MATH = YES; 289 | SWIFT_COMPILATION_MODE = wholemodule; 290 | SWIFT_STRICT_CONCURRENCY = complete; 291 | }; 292 | name = Release; 293 | }; 294 | A07AFD562B989AED004954C9 /* Debug */ = { 295 | isa = XCBuildConfiguration; 296 | buildSettings = { 297 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 298 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 299 | CODE_SIGN_ENTITLEMENTS = PassedDependencies/PassedDependencies.entitlements; 300 | CODE_SIGN_STYLE = Automatic; 301 | CURRENT_PROJECT_VERSION = 1; 302 | DEVELOPMENT_ASSET_PATHS = "\"PassedDependencies/Preview Content\""; 303 | DEVELOPMENT_TEAM = 79L7M968L6; 304 | ENABLE_HARDENED_RUNTIME = YES; 305 | ENABLE_PREVIEWS = YES; 306 | GENERATE_INFOPLIST_FILE = YES; 307 | "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; 308 | "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; 309 | "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; 310 | "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; 311 | "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; 312 | "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; 313 | "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; 314 | "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; 315 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 316 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 317 | IPHONEOS_DEPLOYMENT_TARGET = 17.2; 318 | LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; 319 | "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; 320 | MACOSX_DEPLOYMENT_TARGET = 14.2; 321 | MARKETING_VERSION = 1.0; 322 | PRODUCT_BUNDLE_IDENTIFIER = dev.lucasvandongen.PassedDependencies; 323 | PRODUCT_NAME = "$(TARGET_NAME)"; 324 | SDKROOT = auto; 325 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; 326 | SWIFT_EMIT_LOC_STRINGS = YES; 327 | SWIFT_VERSION = 5.0; 328 | TARGETED_DEVICE_FAMILY = "1,2"; 329 | }; 330 | name = Debug; 331 | }; 332 | A07AFD572B989AED004954C9 /* Release */ = { 333 | isa = XCBuildConfiguration; 334 | buildSettings = { 335 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 336 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 337 | CODE_SIGN_ENTITLEMENTS = PassedDependencies/PassedDependencies.entitlements; 338 | CODE_SIGN_STYLE = Automatic; 339 | CURRENT_PROJECT_VERSION = 1; 340 | DEVELOPMENT_ASSET_PATHS = "\"PassedDependencies/Preview Content\""; 341 | DEVELOPMENT_TEAM = 79L7M968L6; 342 | ENABLE_HARDENED_RUNTIME = YES; 343 | ENABLE_PREVIEWS = YES; 344 | GENERATE_INFOPLIST_FILE = YES; 345 | "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; 346 | "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; 347 | "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; 348 | "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; 349 | "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; 350 | "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; 351 | "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; 352 | "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; 353 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 354 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 355 | IPHONEOS_DEPLOYMENT_TARGET = 17.2; 356 | LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; 357 | "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; 358 | MACOSX_DEPLOYMENT_TARGET = 14.2; 359 | MARKETING_VERSION = 1.0; 360 | PRODUCT_BUNDLE_IDENTIFIER = dev.lucasvandongen.PassedDependencies; 361 | PRODUCT_NAME = "$(TARGET_NAME)"; 362 | SDKROOT = auto; 363 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; 364 | SWIFT_EMIT_LOC_STRINGS = YES; 365 | SWIFT_VERSION = 5.0; 366 | TARGETED_DEVICE_FAMILY = "1,2"; 367 | }; 368 | name = Release; 369 | }; 370 | /* End XCBuildConfiguration section */ 371 | 372 | /* Begin XCConfigurationList section */ 373 | A07AFD412B989AEA004954C9 /* Build configuration list for PBXProject "PassedDependencies" */ = { 374 | isa = XCConfigurationList; 375 | buildConfigurations = ( 376 | A07AFD532B989AED004954C9 /* Debug */, 377 | A07AFD542B989AED004954C9 /* Release */, 378 | ); 379 | defaultConfigurationIsVisible = 0; 380 | defaultConfigurationName = Release; 381 | }; 382 | A07AFD552B989AED004954C9 /* Build configuration list for PBXNativeTarget "PassedDependencies" */ = { 383 | isa = XCConfigurationList; 384 | buildConfigurations = ( 385 | A07AFD562B989AED004954C9 /* Debug */, 386 | A07AFD572B989AED004954C9 /* Release */, 387 | ); 388 | defaultConfigurationIsVisible = 0; 389 | defaultConfigurationName = Release; 390 | }; 391 | /* End XCConfigurationList section */ 392 | 393 | /* Begin XCLocalSwiftPackageReference section */ 394 | A07AFD5A2B989B4F004954C9 /* XCLocalSwiftPackageReference "../SharedDependencies" */ = { 395 | isa = XCLocalSwiftPackageReference; 396 | relativePath = ../SharedDependencies; 397 | }; 398 | /* End XCLocalSwiftPackageReference section */ 399 | 400 | /* Begin XCSwiftPackageProductDependency section */ 401 | A07AFD5B2B989B4F004954C9 /* SharedDependencies */ = { 402 | isa = XCSwiftPackageProductDependency; 403 | productName = SharedDependencies; 404 | }; 405 | /* End XCSwiftPackageProductDependency section */ 406 | }; 407 | rootObject = A07AFD3E2B989AEA004954C9 /* Project object */; 408 | } 409 | -------------------------------------------------------------------------------- /NeedleDependencies/NeedleDependencies.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 60; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | A0107A472BA090F300D3A35B /* NeedleDependenciesApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0107A462BA090F300D3A35B /* NeedleDependenciesApp.swift */; }; 11 | A0107A492BA090F300D3A35B /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0107A482BA090F300D3A35B /* ContentView.swift */; }; 12 | A0107A4B2BA090F600D3A35B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A0107A4A2BA090F600D3A35B /* Assets.xcassets */; }; 13 | A0107A4E2BA090F600D3A35B /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A0107A4D2BA090F600D3A35B /* Preview Assets.xcassets */; }; 14 | A0107A5C2BA099EF00D3A35B /* NeedleGenerated.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0107A5B2BA099EF00D3A35B /* NeedleGenerated.swift */; }; 15 | A0107A5E2BA09ADB00D3A35B /* RootComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0107A5D2BA09ADB00D3A35B /* RootComponent.swift */; }; 16 | A0107A612BA09B7D00D3A35B /* SharedDependencies in Frameworks */ = {isa = PBXBuildFile; productRef = A0107A602BA09B7D00D3A35B /* SharedDependencies */; }; 17 | A0107A632BA0A93B00D3A35B /* LogInComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0107A622BA0A93B00D3A35B /* LogInComponent.swift */; }; 18 | A0107A652BA0A96700D3A35B /* AuthenticatedComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0107A642BA0A96700D3A35B /* AuthenticatedComponent.swift */; }; 19 | CAFD9B772BB2445100B35F4A /* NeedleFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = CAFD9B762BB2445100B35F4A /* NeedleFoundation */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXFileReference section */ 23 | A0107A432BA090F300D3A35B /* NeedleDependencies.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NeedleDependencies.app; sourceTree = BUILT_PRODUCTS_DIR; }; 24 | A0107A462BA090F300D3A35B /* NeedleDependenciesApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NeedleDependenciesApp.swift; sourceTree = ""; }; 25 | A0107A482BA090F300D3A35B /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 26 | A0107A4A2BA090F600D3A35B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 27 | A0107A4D2BA090F600D3A35B /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 28 | A0107A4F2BA090F600D3A35B /* NeedleDependencies.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NeedleDependencies.entitlements; sourceTree = ""; }; 29 | A0107A5B2BA099EF00D3A35B /* NeedleGenerated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NeedleGenerated.swift; sourceTree = ""; }; 30 | A0107A5D2BA09ADB00D3A35B /* RootComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootComponent.swift; sourceTree = ""; }; 31 | A0107A622BA0A93B00D3A35B /* LogInComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogInComponent.swift; sourceTree = ""; }; 32 | A0107A642BA0A96700D3A35B /* AuthenticatedComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticatedComponent.swift; sourceTree = ""; }; 33 | /* End PBXFileReference section */ 34 | 35 | /* Begin PBXFrameworksBuildPhase section */ 36 | A0107A402BA090F300D3A35B /* Frameworks */ = { 37 | isa = PBXFrameworksBuildPhase; 38 | buildActionMask = 2147483647; 39 | files = ( 40 | CAFD9B772BB2445100B35F4A /* NeedleFoundation in Frameworks */, 41 | A0107A612BA09B7D00D3A35B /* SharedDependencies in Frameworks */, 42 | ); 43 | runOnlyForDeploymentPostprocessing = 0; 44 | }; 45 | /* End PBXFrameworksBuildPhase section */ 46 | 47 | /* Begin PBXGroup section */ 48 | A0107A3A2BA090F300D3A35B = { 49 | isa = PBXGroup; 50 | children = ( 51 | A0107A452BA090F300D3A35B /* NeedleDependencies */, 52 | A0107A442BA090F300D3A35B /* Products */, 53 | A0107A572BA0934A00D3A35B /* Frameworks */, 54 | ); 55 | sourceTree = ""; 56 | }; 57 | A0107A442BA090F300D3A35B /* Products */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | A0107A432BA090F300D3A35B /* NeedleDependencies.app */, 61 | ); 62 | name = Products; 63 | sourceTree = ""; 64 | }; 65 | A0107A452BA090F300D3A35B /* NeedleDependencies */ = { 66 | isa = PBXGroup; 67 | children = ( 68 | A0107A5B2BA099EF00D3A35B /* NeedleGenerated.swift */, 69 | A0107A462BA090F300D3A35B /* NeedleDependenciesApp.swift */, 70 | A0107A482BA090F300D3A35B /* ContentView.swift */, 71 | A0107A4A2BA090F600D3A35B /* Assets.xcassets */, 72 | A0107A4F2BA090F600D3A35B /* NeedleDependencies.entitlements */, 73 | A0107A4C2BA090F600D3A35B /* Preview Content */, 74 | A0107A5D2BA09ADB00D3A35B /* RootComponent.swift */, 75 | A0107A622BA0A93B00D3A35B /* LogInComponent.swift */, 76 | A0107A642BA0A96700D3A35B /* AuthenticatedComponent.swift */, 77 | ); 78 | path = NeedleDependencies; 79 | sourceTree = ""; 80 | }; 81 | A0107A4C2BA090F600D3A35B /* Preview Content */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | A0107A4D2BA090F600D3A35B /* Preview Assets.xcassets */, 85 | ); 86 | path = "Preview Content"; 87 | sourceTree = ""; 88 | }; 89 | A0107A572BA0934A00D3A35B /* Frameworks */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | ); 93 | name = Frameworks; 94 | sourceTree = ""; 95 | }; 96 | /* End PBXGroup section */ 97 | 98 | /* Begin PBXNativeTarget section */ 99 | A0107A422BA090F300D3A35B /* NeedleDependencies */ = { 100 | isa = PBXNativeTarget; 101 | buildConfigurationList = A0107A522BA090F600D3A35B /* Build configuration list for PBXNativeTarget "NeedleDependencies" */; 102 | buildPhases = ( 103 | A0107A5A2BA0959D00D3A35B /* Needle */, 104 | A0107A3F2BA090F300D3A35B /* Sources */, 105 | A0107A402BA090F300D3A35B /* Frameworks */, 106 | A0107A412BA090F300D3A35B /* Resources */, 107 | ); 108 | buildRules = ( 109 | ); 110 | dependencies = ( 111 | ); 112 | name = NeedleDependencies; 113 | packageProductDependencies = ( 114 | A0107A602BA09B7D00D3A35B /* SharedDependencies */, 115 | CAFD9B762BB2445100B35F4A /* NeedleFoundation */, 116 | ); 117 | productName = NeedleDependencies; 118 | productReference = A0107A432BA090F300D3A35B /* NeedleDependencies.app */; 119 | productType = "com.apple.product-type.application"; 120 | }; 121 | /* End PBXNativeTarget section */ 122 | 123 | /* Begin PBXProject section */ 124 | A0107A3B2BA090F300D3A35B /* Project object */ = { 125 | isa = PBXProject; 126 | attributes = { 127 | BuildIndependentTargetsInParallel = 1; 128 | LastSwiftUpdateCheck = 1520; 129 | LastUpgradeCheck = 1520; 130 | TargetAttributes = { 131 | A0107A422BA090F300D3A35B = { 132 | CreatedOnToolsVersion = 15.2; 133 | }; 134 | }; 135 | }; 136 | buildConfigurationList = A0107A3E2BA090F300D3A35B /* Build configuration list for PBXProject "NeedleDependencies" */; 137 | compatibilityVersion = "Xcode 14.0"; 138 | developmentRegion = en; 139 | hasScannedForEncodings = 0; 140 | knownRegions = ( 141 | en, 142 | Base, 143 | ); 144 | mainGroup = A0107A3A2BA090F300D3A35B; 145 | packageReferences = ( 146 | A0107A5F2BA09B7D00D3A35B /* XCLocalSwiftPackageReference "../SharedDependencies" */, 147 | CAFD9ABF2BB22F2B00B35F4A /* XCRemoteSwiftPackageReference "needle" */, 148 | ); 149 | productRefGroup = A0107A442BA090F300D3A35B /* Products */; 150 | projectDirPath = ""; 151 | projectRoot = ""; 152 | targets = ( 153 | A0107A422BA090F300D3A35B /* NeedleDependencies */, 154 | ); 155 | }; 156 | /* End PBXProject section */ 157 | 158 | /* Begin PBXResourcesBuildPhase section */ 159 | A0107A412BA090F300D3A35B /* Resources */ = { 160 | isa = PBXResourcesBuildPhase; 161 | buildActionMask = 2147483647; 162 | files = ( 163 | A0107A4E2BA090F600D3A35B /* Preview Assets.xcassets in Resources */, 164 | A0107A4B2BA090F600D3A35B /* Assets.xcassets in Resources */, 165 | ); 166 | runOnlyForDeploymentPostprocessing = 0; 167 | }; 168 | /* End PBXResourcesBuildPhase section */ 169 | 170 | /* Begin PBXShellScriptBuildPhase section */ 171 | A0107A5A2BA0959D00D3A35B /* Needle */ = { 172 | isa = PBXShellScriptBuildPhase; 173 | buildActionMask = 12; 174 | files = ( 175 | ); 176 | inputFileListPaths = ( 177 | ); 178 | inputPaths = ( 179 | ); 180 | name = Needle; 181 | outputFileListPaths = ( 182 | ); 183 | outputPaths = ( 184 | ); 185 | runOnlyForDeploymentPostprocessing = 0; 186 | shellPath = /bin/sh; 187 | shellScript = "#export SOURCEKIT_LOGGING=0 && needle generate ./NeedleDependencies/NeedleGenerated.swift ./ --header-doc ./NeedleDependencies/copyright_header.txt\n"; 188 | }; 189 | /* End PBXShellScriptBuildPhase section */ 190 | 191 | /* Begin PBXSourcesBuildPhase section */ 192 | A0107A3F2BA090F300D3A35B /* Sources */ = { 193 | isa = PBXSourcesBuildPhase; 194 | buildActionMask = 2147483647; 195 | files = ( 196 | A0107A492BA090F300D3A35B /* ContentView.swift in Sources */, 197 | A0107A652BA0A96700D3A35B /* AuthenticatedComponent.swift in Sources */, 198 | A0107A5E2BA09ADB00D3A35B /* RootComponent.swift in Sources */, 199 | A0107A472BA090F300D3A35B /* NeedleDependenciesApp.swift in Sources */, 200 | A0107A632BA0A93B00D3A35B /* LogInComponent.swift in Sources */, 201 | A0107A5C2BA099EF00D3A35B /* NeedleGenerated.swift in Sources */, 202 | ); 203 | runOnlyForDeploymentPostprocessing = 0; 204 | }; 205 | /* End PBXSourcesBuildPhase section */ 206 | 207 | /* Begin XCBuildConfiguration section */ 208 | A0107A502BA090F600D3A35B /* Debug */ = { 209 | isa = XCBuildConfiguration; 210 | buildSettings = { 211 | ALWAYS_SEARCH_USER_PATHS = NO; 212 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 213 | CLANG_ANALYZER_NONNULL = YES; 214 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 215 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 216 | CLANG_ENABLE_MODULES = YES; 217 | CLANG_ENABLE_OBJC_ARC = YES; 218 | CLANG_ENABLE_OBJC_WEAK = YES; 219 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 220 | CLANG_WARN_BOOL_CONVERSION = YES; 221 | CLANG_WARN_COMMA = YES; 222 | CLANG_WARN_CONSTANT_CONVERSION = YES; 223 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 224 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 225 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 226 | CLANG_WARN_EMPTY_BODY = YES; 227 | CLANG_WARN_ENUM_CONVERSION = YES; 228 | CLANG_WARN_INFINITE_RECURSION = YES; 229 | CLANG_WARN_INT_CONVERSION = YES; 230 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 231 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 232 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 233 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 234 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 235 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 236 | CLANG_WARN_STRICT_PROTOTYPES = YES; 237 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 238 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 239 | CLANG_WARN_UNREACHABLE_CODE = YES; 240 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 241 | COPY_PHASE_STRIP = NO; 242 | DEBUG_INFORMATION_FORMAT = dwarf; 243 | ENABLE_STRICT_OBJC_MSGSEND = YES; 244 | ENABLE_TESTABILITY = YES; 245 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 246 | GCC_C_LANGUAGE_STANDARD = gnu17; 247 | GCC_DYNAMIC_NO_PIC = NO; 248 | GCC_NO_COMMON_BLOCKS = YES; 249 | GCC_OPTIMIZATION_LEVEL = 0; 250 | GCC_PREPROCESSOR_DEFINITIONS = ( 251 | "DEBUG=1", 252 | "$(inherited)", 253 | ); 254 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 255 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 256 | GCC_WARN_UNDECLARED_SELECTOR = YES; 257 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 258 | GCC_WARN_UNUSED_FUNCTION = YES; 259 | GCC_WARN_UNUSED_VARIABLE = YES; 260 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 261 | MACOSX_DEPLOYMENT_TARGET = 14.0; 262 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 263 | MTL_FAST_MATH = YES; 264 | ONLY_ACTIVE_ARCH = YES; 265 | SDKROOT = macosx; 266 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; 267 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 268 | SWIFT_STRICT_CONCURRENCY = complete; 269 | }; 270 | name = Debug; 271 | }; 272 | A0107A512BA090F600D3A35B /* Release */ = { 273 | isa = XCBuildConfiguration; 274 | buildSettings = { 275 | ALWAYS_SEARCH_USER_PATHS = NO; 276 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 277 | CLANG_ANALYZER_NONNULL = YES; 278 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 279 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 280 | CLANG_ENABLE_MODULES = YES; 281 | CLANG_ENABLE_OBJC_ARC = YES; 282 | CLANG_ENABLE_OBJC_WEAK = YES; 283 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 284 | CLANG_WARN_BOOL_CONVERSION = YES; 285 | CLANG_WARN_COMMA = YES; 286 | CLANG_WARN_CONSTANT_CONVERSION = YES; 287 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 288 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 289 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 290 | CLANG_WARN_EMPTY_BODY = YES; 291 | CLANG_WARN_ENUM_CONVERSION = YES; 292 | CLANG_WARN_INFINITE_RECURSION = YES; 293 | CLANG_WARN_INT_CONVERSION = YES; 294 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 295 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 296 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 297 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 298 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 299 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 300 | CLANG_WARN_STRICT_PROTOTYPES = YES; 301 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 302 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 303 | CLANG_WARN_UNREACHABLE_CODE = YES; 304 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 305 | COPY_PHASE_STRIP = NO; 306 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 307 | ENABLE_NS_ASSERTIONS = NO; 308 | ENABLE_STRICT_OBJC_MSGSEND = YES; 309 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 310 | GCC_C_LANGUAGE_STANDARD = gnu17; 311 | GCC_NO_COMMON_BLOCKS = YES; 312 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 313 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 314 | GCC_WARN_UNDECLARED_SELECTOR = YES; 315 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 316 | GCC_WARN_UNUSED_FUNCTION = YES; 317 | GCC_WARN_UNUSED_VARIABLE = YES; 318 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 319 | MACOSX_DEPLOYMENT_TARGET = 14.0; 320 | MTL_ENABLE_DEBUG_INFO = NO; 321 | MTL_FAST_MATH = YES; 322 | SDKROOT = macosx; 323 | SWIFT_COMPILATION_MODE = wholemodule; 324 | SWIFT_STRICT_CONCURRENCY = complete; 325 | }; 326 | name = Release; 327 | }; 328 | A0107A532BA090F600D3A35B /* Debug */ = { 329 | isa = XCBuildConfiguration; 330 | buildSettings = { 331 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 332 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 333 | CODE_SIGN_ENTITLEMENTS = NeedleDependencies/NeedleDependencies.entitlements; 334 | CODE_SIGN_STYLE = Automatic; 335 | COMBINE_HIDPI_IMAGES = YES; 336 | CURRENT_PROJECT_VERSION = 1; 337 | DEVELOPMENT_ASSET_PATHS = "\"NeedleDependencies/Preview Content\""; 338 | DEVELOPMENT_TEAM = 79L7M968L6; 339 | ENABLE_HARDENED_RUNTIME = YES; 340 | ENABLE_PREVIEWS = YES; 341 | ENABLE_USER_SCRIPT_SANDBOXING = NO; 342 | GENERATE_INFOPLIST_FILE = YES; 343 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 344 | LD_RUNPATH_SEARCH_PATHS = ( 345 | "$(inherited)", 346 | "@executable_path/../Frameworks", 347 | ); 348 | MARKETING_VERSION = 1.0; 349 | PRODUCT_BUNDLE_IDENTIFIER = dev.lucasvandongen.NeedleDependencies; 350 | PRODUCT_NAME = "$(TARGET_NAME)"; 351 | SWIFT_EMIT_LOC_STRINGS = YES; 352 | SWIFT_VERSION = 5.0; 353 | }; 354 | name = Debug; 355 | }; 356 | A0107A542BA090F600D3A35B /* Release */ = { 357 | isa = XCBuildConfiguration; 358 | buildSettings = { 359 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 360 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 361 | CODE_SIGN_ENTITLEMENTS = NeedleDependencies/NeedleDependencies.entitlements; 362 | CODE_SIGN_STYLE = Automatic; 363 | COMBINE_HIDPI_IMAGES = YES; 364 | CURRENT_PROJECT_VERSION = 1; 365 | DEVELOPMENT_ASSET_PATHS = "\"NeedleDependencies/Preview Content\""; 366 | DEVELOPMENT_TEAM = 79L7M968L6; 367 | ENABLE_HARDENED_RUNTIME = YES; 368 | ENABLE_PREVIEWS = YES; 369 | ENABLE_USER_SCRIPT_SANDBOXING = NO; 370 | GENERATE_INFOPLIST_FILE = YES; 371 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 372 | LD_RUNPATH_SEARCH_PATHS = ( 373 | "$(inherited)", 374 | "@executable_path/../Frameworks", 375 | ); 376 | MARKETING_VERSION = 1.0; 377 | PRODUCT_BUNDLE_IDENTIFIER = dev.lucasvandongen.NeedleDependencies; 378 | PRODUCT_NAME = "$(TARGET_NAME)"; 379 | SWIFT_EMIT_LOC_STRINGS = YES; 380 | SWIFT_VERSION = 5.0; 381 | }; 382 | name = Release; 383 | }; 384 | /* End XCBuildConfiguration section */ 385 | 386 | /* Begin XCConfigurationList section */ 387 | A0107A3E2BA090F300D3A35B /* Build configuration list for PBXProject "NeedleDependencies" */ = { 388 | isa = XCConfigurationList; 389 | buildConfigurations = ( 390 | A0107A502BA090F600D3A35B /* Debug */, 391 | A0107A512BA090F600D3A35B /* Release */, 392 | ); 393 | defaultConfigurationIsVisible = 0; 394 | defaultConfigurationName = Release; 395 | }; 396 | A0107A522BA090F600D3A35B /* Build configuration list for PBXNativeTarget "NeedleDependencies" */ = { 397 | isa = XCConfigurationList; 398 | buildConfigurations = ( 399 | A0107A532BA090F600D3A35B /* Debug */, 400 | A0107A542BA090F600D3A35B /* Release */, 401 | ); 402 | defaultConfigurationIsVisible = 0; 403 | defaultConfigurationName = Release; 404 | }; 405 | /* End XCConfigurationList section */ 406 | 407 | /* Begin XCLocalSwiftPackageReference section */ 408 | A0107A5F2BA09B7D00D3A35B /* XCLocalSwiftPackageReference "../SharedDependencies" */ = { 409 | isa = XCLocalSwiftPackageReference; 410 | relativePath = ../SharedDependencies; 411 | }; 412 | /* End XCLocalSwiftPackageReference section */ 413 | 414 | /* Begin XCRemoteSwiftPackageReference section */ 415 | CAFD9ABF2BB22F2B00B35F4A /* XCRemoteSwiftPackageReference "needle" */ = { 416 | isa = XCRemoteSwiftPackageReference; 417 | repositoryURL = "https://github.com/uber/needle"; 418 | requirement = { 419 | branch = master; 420 | kind = branch; 421 | }; 422 | }; 423 | /* End XCRemoteSwiftPackageReference section */ 424 | 425 | /* Begin XCSwiftPackageProductDependency section */ 426 | A0107A602BA09B7D00D3A35B /* SharedDependencies */ = { 427 | isa = XCSwiftPackageProductDependency; 428 | productName = SharedDependencies; 429 | }; 430 | CAFD9B762BB2445100B35F4A /* NeedleFoundation */ = { 431 | isa = XCSwiftPackageProductDependency; 432 | package = CAFD9ABF2BB22F2B00B35F4A /* XCRemoteSwiftPackageReference "needle" */; 433 | productName = NeedleFoundation; 434 | }; 435 | /* End XCSwiftPackageProductDependency section */ 436 | }; 437 | rootObject = A0107A3B2BA090F300D3A35B /* Project object */; 438 | } 439 | -------------------------------------------------------------------------------- /ComposableDependencies/ComposableDependencies.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 60; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | A00825C92B9617DD002EBCDF /* ComposableDependenciesApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A00825C82B9617DD002EBCDF /* ComposableDependenciesApp.swift */; }; 11 | A00825CB2B9617DD002EBCDF /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A00825CA2B9617DD002EBCDF /* ContentView.swift */; }; 12 | A00825CD2B9617DF002EBCDF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A00825CC2B9617DF002EBCDF /* Assets.xcassets */; }; 13 | A00825D12B9617DF002EBCDF /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A00825D02B9617DF002EBCDF /* Preview Assets.xcassets */; }; 14 | A00825D92B9618D3002EBCDF /* ComposableArchitecture in Frameworks */ = {isa = PBXBuildFile; productRef = A00825D82B9618D3002EBCDF /* ComposableArchitecture */; }; 15 | A0107A682BA1979900D3A35B /* ReducerReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0107A672BA1979900D3A35B /* ReducerReader.swift */; }; 16 | A07AFD3C2B986768004954C9 /* Features.swift in Sources */ = {isa = PBXBuildFile; fileRef = A07AFD3B2B986768004954C9 /* Features.swift */; }; 17 | A0A7D8792B9759B8001CE244 /* Dependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0A7D8782B9759B8001CE244 /* Dependencies.swift */; }; 18 | A0A7D8822B97606B001CE244 /* SharedDependencies in Frameworks */ = {isa = PBXBuildFile; productRef = A0A7D8812B97606B001CE244 /* SharedDependencies */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXFileReference section */ 22 | A00825C52B9617DD002EBCDF /* ComposableDependencies.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ComposableDependencies.app; sourceTree = BUILT_PRODUCTS_DIR; }; 23 | A00825C82B9617DD002EBCDF /* ComposableDependenciesApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposableDependenciesApp.swift; sourceTree = ""; }; 24 | A00825CA2B9617DD002EBCDF /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 25 | A00825CC2B9617DF002EBCDF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 26 | A00825CE2B9617DF002EBCDF /* ComposableDependencies.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ComposableDependencies.entitlements; sourceTree = ""; }; 27 | A00825D02B9617DF002EBCDF /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 28 | A0107A672BA1979900D3A35B /* ReducerReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReducerReader.swift; sourceTree = ""; }; 29 | A07AFD3B2B986768004954C9 /* Features.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Features.swift; sourceTree = ""; }; 30 | A0A7D8782B9759B8001CE244 /* Dependencies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dependencies.swift; sourceTree = ""; }; 31 | /* End PBXFileReference section */ 32 | 33 | /* Begin PBXFrameworksBuildPhase section */ 34 | A00825C22B9617DD002EBCDF /* Frameworks */ = { 35 | isa = PBXFrameworksBuildPhase; 36 | buildActionMask = 2147483647; 37 | files = ( 38 | A0A7D8822B97606B001CE244 /* SharedDependencies in Frameworks */, 39 | A00825D92B9618D3002EBCDF /* ComposableArchitecture in Frameworks */, 40 | ); 41 | runOnlyForDeploymentPostprocessing = 0; 42 | }; 43 | /* End PBXFrameworksBuildPhase section */ 44 | 45 | /* Begin PBXGroup section */ 46 | A00825BC2B9617DD002EBCDF = { 47 | isa = PBXGroup; 48 | children = ( 49 | A00825C72B9617DD002EBCDF /* ComposableDependencies */, 50 | A00825C62B9617DD002EBCDF /* Products */, 51 | ); 52 | sourceTree = ""; 53 | }; 54 | A00825C62B9617DD002EBCDF /* Products */ = { 55 | isa = PBXGroup; 56 | children = ( 57 | A00825C52B9617DD002EBCDF /* ComposableDependencies.app */, 58 | ); 59 | name = Products; 60 | sourceTree = ""; 61 | }; 62 | A00825C72B9617DD002EBCDF /* ComposableDependencies */ = { 63 | isa = PBXGroup; 64 | children = ( 65 | A0107A662BA1978B00D3A35B /* ReducerReader */, 66 | A00825C82B9617DD002EBCDF /* ComposableDependenciesApp.swift */, 67 | A00825CA2B9617DD002EBCDF /* ContentView.swift */, 68 | A00825CC2B9617DF002EBCDF /* Assets.xcassets */, 69 | A00825CE2B9617DF002EBCDF /* ComposableDependencies.entitlements */, 70 | A00825CF2B9617DF002EBCDF /* Preview Content */, 71 | A0A7D8782B9759B8001CE244 /* Dependencies.swift */, 72 | A07AFD3B2B986768004954C9 /* Features.swift */, 73 | ); 74 | path = ComposableDependencies; 75 | sourceTree = ""; 76 | }; 77 | A00825CF2B9617DF002EBCDF /* Preview Content */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | A00825D02B9617DF002EBCDF /* Preview Assets.xcassets */, 81 | ); 82 | path = "Preview Content"; 83 | sourceTree = ""; 84 | }; 85 | A0107A662BA1978B00D3A35B /* ReducerReader */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | A0107A672BA1979900D3A35B /* ReducerReader.swift */, 89 | ); 90 | path = ReducerReader; 91 | sourceTree = ""; 92 | }; 93 | /* End PBXGroup section */ 94 | 95 | /* Begin PBXNativeTarget section */ 96 | A00825C42B9617DD002EBCDF /* ComposableDependencies */ = { 97 | isa = PBXNativeTarget; 98 | buildConfigurationList = A00825D42B9617DF002EBCDF /* Build configuration list for PBXNativeTarget "ComposableDependencies" */; 99 | buildPhases = ( 100 | A00825C12B9617DD002EBCDF /* Sources */, 101 | A00825C22B9617DD002EBCDF /* Frameworks */, 102 | A00825C32B9617DD002EBCDF /* Resources */, 103 | ); 104 | buildRules = ( 105 | ); 106 | dependencies = ( 107 | ); 108 | name = ComposableDependencies; 109 | packageProductDependencies = ( 110 | A00825D82B9618D3002EBCDF /* ComposableArchitecture */, 111 | A0A7D8812B97606B001CE244 /* SharedDependencies */, 112 | ); 113 | productName = ComposableDependencies; 114 | productReference = A00825C52B9617DD002EBCDF /* ComposableDependencies.app */; 115 | productType = "com.apple.product-type.application"; 116 | }; 117 | /* End PBXNativeTarget section */ 118 | 119 | /* Begin PBXProject section */ 120 | A00825BD2B9617DD002EBCDF /* Project object */ = { 121 | isa = PBXProject; 122 | attributes = { 123 | BuildIndependentTargetsInParallel = 1; 124 | LastSwiftUpdateCheck = 1520; 125 | LastUpgradeCheck = 1520; 126 | TargetAttributes = { 127 | A00825C42B9617DD002EBCDF = { 128 | CreatedOnToolsVersion = 15.2; 129 | }; 130 | }; 131 | }; 132 | buildConfigurationList = A00825C02B9617DD002EBCDF /* Build configuration list for PBXProject "ComposableDependencies" */; 133 | compatibilityVersion = "Xcode 14.0"; 134 | developmentRegion = en; 135 | hasScannedForEncodings = 0; 136 | knownRegions = ( 137 | en, 138 | Base, 139 | ); 140 | mainGroup = A00825BC2B9617DD002EBCDF; 141 | packageReferences = ( 142 | A00825D72B9618D3002EBCDF /* XCRemoteSwiftPackageReference "swift-composable-architecture" */, 143 | A0A7D8802B97606B001CE244 /* XCLocalSwiftPackageReference "../SharedDependencies" */, 144 | ); 145 | productRefGroup = A00825C62B9617DD002EBCDF /* Products */; 146 | projectDirPath = ""; 147 | projectRoot = ""; 148 | targets = ( 149 | A00825C42B9617DD002EBCDF /* ComposableDependencies */, 150 | ); 151 | }; 152 | /* End PBXProject section */ 153 | 154 | /* Begin PBXResourcesBuildPhase section */ 155 | A00825C32B9617DD002EBCDF /* Resources */ = { 156 | isa = PBXResourcesBuildPhase; 157 | buildActionMask = 2147483647; 158 | files = ( 159 | A00825D12B9617DF002EBCDF /* Preview Assets.xcassets in Resources */, 160 | A00825CD2B9617DF002EBCDF /* Assets.xcassets in Resources */, 161 | ); 162 | runOnlyForDeploymentPostprocessing = 0; 163 | }; 164 | /* End PBXResourcesBuildPhase section */ 165 | 166 | /* Begin PBXSourcesBuildPhase section */ 167 | A00825C12B9617DD002EBCDF /* Sources */ = { 168 | isa = PBXSourcesBuildPhase; 169 | buildActionMask = 2147483647; 170 | files = ( 171 | A07AFD3C2B986768004954C9 /* Features.swift in Sources */, 172 | A0A7D8792B9759B8001CE244 /* Dependencies.swift in Sources */, 173 | A0107A682BA1979900D3A35B /* ReducerReader.swift in Sources */, 174 | A00825CB2B9617DD002EBCDF /* ContentView.swift in Sources */, 175 | A00825C92B9617DD002EBCDF /* ComposableDependenciesApp.swift in Sources */, 176 | ); 177 | runOnlyForDeploymentPostprocessing = 0; 178 | }; 179 | /* End PBXSourcesBuildPhase section */ 180 | 181 | /* Begin XCBuildConfiguration section */ 182 | A00825D22B9617DF002EBCDF /* Debug */ = { 183 | isa = XCBuildConfiguration; 184 | buildSettings = { 185 | ALWAYS_SEARCH_USER_PATHS = NO; 186 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 187 | CLANG_ANALYZER_NONNULL = YES; 188 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 189 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 190 | CLANG_ENABLE_MODULES = YES; 191 | CLANG_ENABLE_OBJC_ARC = YES; 192 | CLANG_ENABLE_OBJC_WEAK = YES; 193 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 194 | CLANG_WARN_BOOL_CONVERSION = YES; 195 | CLANG_WARN_COMMA = YES; 196 | CLANG_WARN_CONSTANT_CONVERSION = YES; 197 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 198 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 199 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 200 | CLANG_WARN_EMPTY_BODY = YES; 201 | CLANG_WARN_ENUM_CONVERSION = YES; 202 | CLANG_WARN_INFINITE_RECURSION = YES; 203 | CLANG_WARN_INT_CONVERSION = YES; 204 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 205 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 206 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 207 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 208 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 209 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 210 | CLANG_WARN_STRICT_PROTOTYPES = YES; 211 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 212 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 213 | CLANG_WARN_UNREACHABLE_CODE = YES; 214 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 215 | COPY_PHASE_STRIP = NO; 216 | DEBUG_INFORMATION_FORMAT = dwarf; 217 | ENABLE_STRICT_OBJC_MSGSEND = YES; 218 | ENABLE_TESTABILITY = YES; 219 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 220 | GCC_C_LANGUAGE_STANDARD = gnu17; 221 | GCC_DYNAMIC_NO_PIC = NO; 222 | GCC_NO_COMMON_BLOCKS = YES; 223 | GCC_OPTIMIZATION_LEVEL = 0; 224 | GCC_PREPROCESSOR_DEFINITIONS = ( 225 | "DEBUG=1", 226 | "$(inherited)", 227 | ); 228 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 229 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 230 | GCC_WARN_UNDECLARED_SELECTOR = YES; 231 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 232 | GCC_WARN_UNUSED_FUNCTION = YES; 233 | GCC_WARN_UNUSED_VARIABLE = YES; 234 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 235 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 236 | MTL_FAST_MATH = YES; 237 | ONLY_ACTIVE_ARCH = YES; 238 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; 239 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 240 | SWIFT_STRICT_CONCURRENCY = complete; 241 | }; 242 | name = Debug; 243 | }; 244 | A00825D32B9617DF002EBCDF /* Release */ = { 245 | isa = XCBuildConfiguration; 246 | buildSettings = { 247 | ALWAYS_SEARCH_USER_PATHS = NO; 248 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 249 | CLANG_ANALYZER_NONNULL = YES; 250 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 251 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 252 | CLANG_ENABLE_MODULES = YES; 253 | CLANG_ENABLE_OBJC_ARC = YES; 254 | CLANG_ENABLE_OBJC_WEAK = YES; 255 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 256 | CLANG_WARN_BOOL_CONVERSION = YES; 257 | CLANG_WARN_COMMA = YES; 258 | CLANG_WARN_CONSTANT_CONVERSION = YES; 259 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 260 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 261 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 262 | CLANG_WARN_EMPTY_BODY = YES; 263 | CLANG_WARN_ENUM_CONVERSION = YES; 264 | CLANG_WARN_INFINITE_RECURSION = YES; 265 | CLANG_WARN_INT_CONVERSION = YES; 266 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 267 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 268 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 269 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 270 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 271 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 272 | CLANG_WARN_STRICT_PROTOTYPES = YES; 273 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 274 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 275 | CLANG_WARN_UNREACHABLE_CODE = YES; 276 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 277 | COPY_PHASE_STRIP = NO; 278 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 279 | ENABLE_NS_ASSERTIONS = NO; 280 | ENABLE_STRICT_OBJC_MSGSEND = YES; 281 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 282 | GCC_C_LANGUAGE_STANDARD = gnu17; 283 | GCC_NO_COMMON_BLOCKS = YES; 284 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 285 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 286 | GCC_WARN_UNDECLARED_SELECTOR = YES; 287 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 288 | GCC_WARN_UNUSED_FUNCTION = YES; 289 | GCC_WARN_UNUSED_VARIABLE = YES; 290 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 291 | MTL_ENABLE_DEBUG_INFO = NO; 292 | MTL_FAST_MATH = YES; 293 | SWIFT_COMPILATION_MODE = wholemodule; 294 | SWIFT_STRICT_CONCURRENCY = complete; 295 | }; 296 | name = Release; 297 | }; 298 | A00825D52B9617DF002EBCDF /* Debug */ = { 299 | isa = XCBuildConfiguration; 300 | buildSettings = { 301 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 302 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 303 | CODE_SIGN_ENTITLEMENTS = ComposableDependencies/ComposableDependencies.entitlements; 304 | CODE_SIGN_STYLE = Automatic; 305 | CURRENT_PROJECT_VERSION = 1; 306 | DEVELOPMENT_ASSET_PATHS = "\"ComposableDependencies/Preview Content\""; 307 | DEVELOPMENT_TEAM = 79L7M968L6; 308 | ENABLE_HARDENED_RUNTIME = YES; 309 | ENABLE_PREVIEWS = YES; 310 | GENERATE_INFOPLIST_FILE = YES; 311 | "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; 312 | "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; 313 | "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; 314 | "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; 315 | "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; 316 | "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; 317 | "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; 318 | "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; 319 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 320 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 321 | IPHONEOS_DEPLOYMENT_TARGET = 17.2; 322 | LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; 323 | "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; 324 | MACOSX_DEPLOYMENT_TARGET = 14.2; 325 | MARKETING_VERSION = 1.0; 326 | PRODUCT_BUNDLE_IDENTIFIER = dev.lucasvandongen.ComposableDependencies; 327 | PRODUCT_NAME = "$(TARGET_NAME)"; 328 | SDKROOT = auto; 329 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; 330 | SWIFT_EMIT_LOC_STRINGS = YES; 331 | SWIFT_VERSION = 5.0; 332 | TARGETED_DEVICE_FAMILY = "1,2"; 333 | }; 334 | name = Debug; 335 | }; 336 | A00825D62B9617DF002EBCDF /* Release */ = { 337 | isa = XCBuildConfiguration; 338 | buildSettings = { 339 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 340 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 341 | CODE_SIGN_ENTITLEMENTS = ComposableDependencies/ComposableDependencies.entitlements; 342 | CODE_SIGN_STYLE = Automatic; 343 | CURRENT_PROJECT_VERSION = 1; 344 | DEVELOPMENT_ASSET_PATHS = "\"ComposableDependencies/Preview Content\""; 345 | DEVELOPMENT_TEAM = 79L7M968L6; 346 | ENABLE_HARDENED_RUNTIME = YES; 347 | ENABLE_PREVIEWS = YES; 348 | GENERATE_INFOPLIST_FILE = YES; 349 | "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; 350 | "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; 351 | "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; 352 | "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; 353 | "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; 354 | "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; 355 | "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; 356 | "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; 357 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 358 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 359 | IPHONEOS_DEPLOYMENT_TARGET = 17.2; 360 | LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; 361 | "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; 362 | MACOSX_DEPLOYMENT_TARGET = 14.2; 363 | MARKETING_VERSION = 1.0; 364 | PRODUCT_BUNDLE_IDENTIFIER = dev.lucasvandongen.ComposableDependencies; 365 | PRODUCT_NAME = "$(TARGET_NAME)"; 366 | SDKROOT = auto; 367 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; 368 | SWIFT_EMIT_LOC_STRINGS = YES; 369 | SWIFT_VERSION = 5.0; 370 | TARGETED_DEVICE_FAMILY = "1,2"; 371 | }; 372 | name = Release; 373 | }; 374 | /* End XCBuildConfiguration section */ 375 | 376 | /* Begin XCConfigurationList section */ 377 | A00825C02B9617DD002EBCDF /* Build configuration list for PBXProject "ComposableDependencies" */ = { 378 | isa = XCConfigurationList; 379 | buildConfigurations = ( 380 | A00825D22B9617DF002EBCDF /* Debug */, 381 | A00825D32B9617DF002EBCDF /* Release */, 382 | ); 383 | defaultConfigurationIsVisible = 0; 384 | defaultConfigurationName = Release; 385 | }; 386 | A00825D42B9617DF002EBCDF /* Build configuration list for PBXNativeTarget "ComposableDependencies" */ = { 387 | isa = XCConfigurationList; 388 | buildConfigurations = ( 389 | A00825D52B9617DF002EBCDF /* Debug */, 390 | A00825D62B9617DF002EBCDF /* Release */, 391 | ); 392 | defaultConfigurationIsVisible = 0; 393 | defaultConfigurationName = Release; 394 | }; 395 | /* End XCConfigurationList section */ 396 | 397 | /* Begin XCLocalSwiftPackageReference section */ 398 | A0A7D8802B97606B001CE244 /* XCLocalSwiftPackageReference "../SharedDependencies" */ = { 399 | isa = XCLocalSwiftPackageReference; 400 | relativePath = ../SharedDependencies; 401 | }; 402 | /* End XCLocalSwiftPackageReference section */ 403 | 404 | /* Begin XCRemoteSwiftPackageReference section */ 405 | A00825D72B9618D3002EBCDF /* XCRemoteSwiftPackageReference "swift-composable-architecture" */ = { 406 | isa = XCRemoteSwiftPackageReference; 407 | repositoryURL = "https://github.com/pointfreeco/swift-composable-architecture"; 408 | requirement = { 409 | kind = upToNextMajorVersion; 410 | minimumVersion = 1.9.1; 411 | }; 412 | }; 413 | /* End XCRemoteSwiftPackageReference section */ 414 | 415 | /* Begin XCSwiftPackageProductDependency section */ 416 | A00825D82B9618D3002EBCDF /* ComposableArchitecture */ = { 417 | isa = XCSwiftPackageProductDependency; 418 | package = A00825D72B9618D3002EBCDF /* XCRemoteSwiftPackageReference "swift-composable-architecture" */; 419 | productName = ComposableArchitecture; 420 | }; 421 | A0A7D8812B97606B001CE244 /* SharedDependencies */ = { 422 | isa = XCSwiftPackageProductDependency; 423 | productName = SharedDependencies; 424 | }; 425 | /* End XCSwiftPackageProductDependency section */ 426 | }; 427 | rootObject = A00825BD2B9617DD002EBCDF /* Project object */; 428 | } 429 | --------------------------------------------------------------------------------