如何向TaskService类的doSomething函数注入TaskDetails实例
给TaskService注入TaskDetails的几种最佳方案
先补个基础代码示例,方便理解场景:
// 示例基础类 struct Task: Identifiable { let id: UUID let title: String let date: Int // 用Int代替日期做演示 } struct TaskDetails { let task: Task // 假设有衍生的计算属性 var formattedDate: String { "\(task.date)" } } class TaskService { func doSomething(taskDetails: TaskDetails) { // 处理TaskDetails的业务逻辑 print("处理任务:\(taskDetails.task.title),日期:\(taskDetails.formattedDate)") } }
1. 构造注入(首推,降低耦合)
如果TaskService需要频繁处理TaskDetails,或者你想让它不用关心TaskDetails的创建规则,直接把创建TaskDetails的工厂方法注入到TaskService的构造器里就行。这样后续TaskDetails的初始化逻辑变了,只改工厂,不用动TaskService的代码。
代码示例:
// 定义工厂类型,本质就是个接收Task返回TaskDetails的闭包 typealias TaskDetailsFactory = (Task) -> TaskDetails class TaskService { private let taskDetailsFactory: TaskDetailsFactory // 构造器里注入工厂 init(taskDetailsFactory: @escaping TaskDetailsFactory) { self.taskDetailsFactory = taskDetailsFactory } // 对外暴露更友好的接口,直接传Task就行 func doSomething(with task: Task) { let details = taskDetailsFactory(task) // 原业务逻辑 print("处理任务:\(details.task.title),日期:\(details.formattedDate)") } } // 使用方式 let service = TaskService(taskDetailsFactory: TaskDetails.init) let testTask = Task(id: UUID(), title: "测试任务", date: 20240520) service.doSomething(with: testTask)
2. 直接传实例(简单直接,适合临时调用)
如果只是偶尔调用doSomething,就像你现在在ForEach里做的那样,直接创建好TaskDetails传进去就行。要是多个地方都要这么写,可以把创建逻辑抽成个工具方法,避免重复代码。
SwiftUI视图里的示例:
struct TaskListView: View { let tasks: [Task] // 实际项目里建议用环境注入,别直接初始化 let taskService = TaskService() var body: some View { List(tasks) { item in Button("处理任务") { let details = TaskDetails(task: item) taskService.doSomething(taskDetails: details) } } } }
3. SwiftUI环境注入(适合多视图共享)
如果你的TaskService要在多个SwiftUI视图里用,把它塞进环境里是最方便的,还能顺便把TaskDetails的创建逻辑也整合进去:
// 定义环境键 struct TaskServiceKey: EnvironmentKey { static let defaultValue: TaskService = TaskService(taskDetailsFactory: TaskDetails.init) } extension EnvironmentValues { var taskService: TaskService { get { self[TaskServiceKey.self] } set { self[TaskServiceKey.self] = newValue } } } // 父视图里注入自定义的TaskService struct ParentView: View { var body: some View { TaskListView(tasks: testTasks) .environment(\.taskService, TaskService(taskDetailsFactory: TaskDetails.init)) } } // 子视图直接从环境取 struct TaskListView: View { let tasks: [Task] @Environment(\.taskService) private var taskService var body: some View { List(tasks) { item in Button("处理任务") { let details = taskService.taskDetailsFactory(item) taskService.doSomething(taskDetails: details) } } } }
4. 静态工厂方法(适合简单场景)
要是TaskDetails的创建逻辑固定死了,不会变,直接在TaskService里整个静态方法来创建TaskDetails就行,省得外面重复写:
extension TaskService { static func makeTaskDetails(for task: Task) -> TaskDetails { TaskDetails(task: task) } } // 使用 let details = TaskService.makeTaskDetails(for: testTask) taskService.doSomething(taskDetails: details)
内容的提问来源于stack exchange,提问作者fs_tigre
相关产品推荐
相关产品推荐

