Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import DevLogInfra

class AppDelegate: UIResponder, UIApplicationDelegate {
private let logger = Logger(category: "AppDelegate")
private let container = AppDIContainer.shared
private let container = AppDIContainer.default

func application(
_ app: UIApplication,
Expand Down
2 changes: 1 addition & 1 deletion Application/DevLogApp/Sources/App/DevLogApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ struct DevLogApp: App {
@State private var windowEvent = TodoEditorWindowEvent()

init() {
AppAssembler().assemble(AppDIContainer.shared)
AppAssembler().assemble(AppDIContainer.default)
}

var body: some Scene {
Expand Down
6 changes: 3 additions & 3 deletions Application/DevLogCore/Sources/DIContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public enum DependencyScope {
case transient
}

public protocol DIContainer {
public protocol DIContainer: Sendable {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

DIContainer 프로토콜이 Sendable을 채택함에 따라, 멀티스레드 및 서로 다른 액터 환경에서 안전하게 공유될 수 있어야 합니다.

현재 register 메서드의 factory 클로저는 @Sendable 타입이 아닙니다. 이로 인해 서로 다른 격리 컨텍스트(Isolation Context)에서 resolve를 통해 의존성을 생성할 때 데이터 레이스(Data Race)가 발생할 수 있습니다.

스레드 안전성을 보장하기 위해 구체 구현 클래스보다는 프로토콜(추상화) 수준에서 Sendable 적합성을 선언하고, DIContainer 프로토콜의 factory 클로저에 @Sendable을 추가하는 것을 권장합니다.

public protocol DIContainer: Sendable {
    func register<T>(
        _ type: T.Type,
        name: DependencyName?,
        scope: DependencyScope,
        _ factory: @escaping @Sendable () -> T
    )
    // ...
}
References
  1. Write all review comments in Korean and keep them concise and high-signal. (link)
  2. When applying Sendable conformance to ensure thread safety, prefer declaring Sendable on the protocol (abstraction) rather than the concrete implementation class.

func register<T>(
_ type: T.Type,
name: DependencyName?,
Expand All @@ -50,8 +50,8 @@ public extension DIContainer {
}
}

public final class AppDIContainer: DIContainer {
public static let shared = AppDIContainer()
public final class AppDIContainer: DIContainer, @unchecked Sendable {
public static let `default` = AppDIContainer()

private let lock = NSRecursiveLock()

Expand Down
2 changes: 1 addition & 1 deletion Application/DevLogCore/Sources/DIContainerKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import SwiftUI

private struct DIContainerKey: EnvironmentKey {
static let defaultValue: any DIContainer = AppDIContainer.shared
static let defaultValue: any DIContainer = AppDIContainer.default
}

public extension EnvironmentValues {
Expand Down
6 changes: 3 additions & 3 deletions Application/DevLogCore/Sources/PushNotificationQuery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@

import Foundation

public struct PushNotificationQuery: Equatable {
public enum SortOrder: Equatable {
public struct PushNotificationQuery: Equatable, Sendable {
public enum SortOrder: Equatable, Sendable {
case latest
case oldest
}

public enum TimeFilter: Equatable, Hashable {
public enum TimeFilter: Equatable, Hashable, Sendable {
case none
case hours(Int)
case days(Int)
Expand Down
10 changes: 5 additions & 5 deletions Tuist/ProjectDescriptionHelpers/Project+Settings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ public extension Settings {
"CURRENT_PROJECT_VERSION": "1",
"INFOPLIST_KEY_CFBundleShortVersionString": "$(MARKETING_VERSION)",
"INFOPLIST_KEY_CFBundleVersion": "$(CURRENT_PROJECT_VERSION)",
"SWIFT_VERSION": "5.0",
"TARGETED_DEVICE_FAMILY": "1,2",
"SWIFT_VERSION": "6.0",
"TARGETED_DEVICE_FAMILY": "1,2"
]
commonBase.merge(base) { _, new in new }

Expand All @@ -26,7 +26,7 @@ public extension Settings {
base: commonBase,
configurations: [
.debug(name: "Debug", settings: debug, xcconfig: versionXcconfigPath),
.release(name: "Release", settings: release, xcconfig: versionXcconfigPath),
.release(name: "Release", settings: release, xcconfig: versionXcconfigPath)
],
defaultSettings: defaultSettings
)
Expand All @@ -36,7 +36,7 @@ public extension Settings {
base: commonBase,
configurations: [
.debug(name: "Debug", settings: debug),
.release(name: "Release", settings: release),
.release(name: "Release", settings: release)
],
defaultSettings: defaultSettings
)
Expand All @@ -50,7 +50,7 @@ public extension Settings {
"ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS": "YES",
"DEVELOPMENT_TEAM": DevLogSigning.teamID,
"ENABLE_USER_SCRIPT_SANDBOXING": "YES",
"STRING_CATALOG_GENERATE_SYMBOLS": "YES",
"STRING_CATALOG_GENERATE_SYMBOLS": "YES"
]
base.merge(additionalBase) { _, new in new }
return .devlog(versionXcconfigPath: versionXcconfigPath, base: base)
Expand Down
Loading