一个库,用于在使用协议时使 swift-dependencies 更加有用。
Xcode 对面向协议的声明和实现的支持非常强大。但是,正如我们在 Point-Free 的一集中所理解的那样,我们为此付出了代价,以换取一些灵活性。那么,有没有一种方法可以在获得两者优势的同时向前推进?是的,那就是宏!宏允许我们自动将基于协议的代码转换为基于结构体的代码。这是一种非常有效的方法。通过将实现存放在宏中,协议就变成了一个可以被 Xcode 辅助的实体,并在内部转换为实现的函数调用。
这是一个扩展 swift-dependencies 的库。 swift-dependencies 在这里。
https://github.com/pointfreeco/swift-dependencies
先看看这个。Swift 宏的强大功能使得可以切出和重写单个函数,即使它是在协议中实现的。
import DependenciesExtrasMacros
import Foundation
@DependencyProtocolClient(implemented: ProtocolPersistentImpl.self)
protocol ProtocolPersistent: Sendable {
func load(_ url: URL) throws -> Data
func save(_ data: Data, _ url: URL) async throws -> Void
}
public final class ProtocolPersistentImpl: @unchecked Sendable, ProtocolPersistent {
func load(_ url: URL) throws -> Data { try Data(contentsOf: url) }
func save(_ data: Data, _ url: URL) async throws -> Void { try data.write(to: url) }
}
extension DependencyValues {
#DependencyValueRegister(of: ProtocolPersistent.self, into: "protocolPersistent")
}
struct Runner {
@Dependency(\.protocolPersistent) var protocolPersistent
func run() async throws {
do {
let new = withDependencies {
$0.protocolPersistent.save = { data, url in debugPrint(data, url) }
} operation: {
protocolPersistent
}
try await new.save("struct".data(using: .utf8)!, URL.documentsDirectory.appendingPathComponent(UUID().uuidString, conformingTo: .text))
}
}
}
第一步是为已经存在的协议提供一个宏,告知世界这将用于依赖解析。
+ @DependencyProtocolClient(implemented: ProtocolPersistentImpl.self)
protocol ProtocolPersistent: Sendable {
func load(_ url: URL) throws -> Data
func save(_ data: Data, _ url: URL) async throws -> Void
}
接下来,在 DependencyValues 中注册一个结构体,该结构体符合宏生成的 DependencyKey。
+ extension DependencyValues {
+ #DependencyValueRegister(of: ProtocolPersistent.self, into: "protocolPersistent")
+ }
这样就结束了我们需要亲力亲为的需求!这是事情开始运作的唯一方法。如果它不起作用或有您不期望的行为,请给我们反馈。我们欢迎您的贡献!
Dependencies API 的最新文档可在此处获得:here(这里)。
您可以通过将 Dependencies 添加到您的项目中作为一个包,将其添加到 Xcode 项目中。
如果您想在 SwiftPM 项目中使用 Dependencies,只需将其添加到您的 Package.swift
中即可。
dependencies: [
.package(url: "https://github.com/arasan01/swift-dependencies-extras", from: "0.1.0")
]
然后将产品添加到任何需要访问该库的目标中。
.product(name: "DependenciesExtrasMacros", package: "swift-dependencies-extras"),
自动重写由 PointFree 风格的基于 swift-dependencies 的 Protocol、Class 和 Struct 组成的传统设计,允许逐个重写每个实现的函数。
此库根据 MIT 许可证发布。 有关详细信息,请参阅 LICENSE。