From 9f91eb3b17102ea4fb04ba12af9a0275b7b98729 Mon Sep 17 00:00:00 2001 From: Dan Federman Date: Thu, 16 Jan 2025 14:20:36 -0800 Subject: [PATCH] Document recommendations for root object selection (#148) --- Documentation/Manual.md | 12 ++++++++++-- README.md | 8 ++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Documentation/Manual.md b/Documentation/Manual.md index 65a15748..73e28b99 100644 --- a/Documentation/Manual.md +++ b/Documentation/Manual.md @@ -404,9 +404,17 @@ In a manual DI system it is simple for superclasses to receive injected dependen It is strongly recommended that projects adopting SafeDI start their migration by identifying the root of their dependency tree and making it `@Instantiable(isRoot: true)`. Once your root object has adopted SafeDI, continue migrating dependencies to SafeDI in either a breadth-first or depth-first manner. As your adoption of SafeDI progresses, you’ll find that you are removing more code than you are adding: many of your dependencies are likely being passed through intermediary objects that do not utilize the dependency except to instantiate a dependency deeper in the tree. Once types further down the dependency tree have adopted SafeDI, you will be able to avoid receiving dependencies in intermediary types. -## Example Application +### Selecting a root in SwiftUI applications -We’ve tied everything together with an example multi-user notes application backed by SwiftUI. You can compile and run this code in Xcode in the included [ExampleProjectIntegration](../Examples/ExampleProjectIntegration) project. +SwiftUI applications have a natural root: the `App`-conforming type that is initialized when the binary is launched. + +### Selecting a root in UIKit applications + +UIKit applications’ natural root is the `UIApplicationDelegate`-conforming app delegate, however, this type inherits from the Objective-C `NSObject` which already has a no-argument `init()`. As such, it is best to create a custom `@Instantiable(isRoot: true) public final class Root: Instantiable` type that is initialized and stored by the application’s app delegate. + +## Example applications + +We’ve tied everything together with an example multi-user notes application backed by SwiftUI. You can compile and run this code in [an example single-module Xcode project](../Examples/ExampleProjectIntegration). This same multi-user notes app also exists in [an example multi-module Xcode project](../Examples/ExampleMultiProjectIntegration), and also in [an example Xcode project using CocoaPods](../Examples/ExampleCocoaPodsIntegration). We have also created [an example multi-module `Package.swift` that integrates with SafeDI](../Examples/ExamplePackageIntegration). ## Under the hood diff --git a/README.md b/README.md index 3aa30fb9..905a9d5a 100644 --- a/README.md +++ b/README.md @@ -116,17 +116,13 @@ You can see this integration in practice in the [ExamplePackageIntegration](Exam #### CocoaPods -Use a pre-build script ([example](Examples/ExampleCocoaPodsIntegration/safeditool.sh)) to download the `SafeDITool` binary and generate your SafeDI dependency tree. Make sure to set `ENABLE_USER_SCRIPT_SANDBOXING` to `NO` in the target running the pre-build script. +Use a pre-build script to download the `SafeDITool` binary and generate your SafeDI dependency tree ([example](Examples/ExampleCocoaPodsIntegration/safeditool.sh)). Make sure to set `ENABLE_USER_SCRIPT_SANDBOXING` to `NO` in the target running the pre-build script. You can see this integration in practice in the [ExampleCocoaPodsIntegration](Examples/ExampleCocoaPodsIntegration) package. Run `bundle exec pod install --project-directory=Examples/ExampleCocoaPodsIntegration` to create the `ExampleCocoaPodsIntegration.xcworkspace`. #### Additional configurations -If your first-party code comprises multiple modules in Xcode, or a mix of Xcode Projects and Swift Packages, or some other configuration, once your Xcode project depends on the SafeDI package you will need to utilize the `SafeDITool` command-line executable directly in a pre-build script similar to the CocoaPods integration described above. - -You can see this integration in practice in the [ExampleMultiProjectIntegration](Examples/ExampleMultiProjectIntegration) package. - -`SafeDITool` is designed to integrate into projects of any size or shape. +`SafeDITool` is designed to integrate into projects of any size or shape. If your first-party code comprises multiple modules in Xcode, or a mix of Xcode Projects and Swift Packages, or some other configuration, once your Xcode project depends on the SafeDI package you will need to utilize the `SafeDITool` command-line executable directly in a pre-build script similar to the CocoaPods integration described above. `SafeDITool` can parse all of your Swift files at once, or for even better performance, the tool can be run on each dependent module as part of the build. Run `swift run SafeDITool --help` to see documentation of the tool’s supported arguments.