gpt4 book ai didi

swift - 基于消息的体系结构中的通用消息

转载 作者:搜寻专家 更新时间:2023-10-30 21:59:52 24 4
gpt4 key购买 nike

我正在 Swift 中试验基于消息的架构。例如,我正在尝试做一些类似于 Elm 架构的事情。这是我的代码的样子:

enum SideEffect<Message> {

case sendRequest((String) -> Message)
}

protocol Component {

associatedtype Message

mutating func send(msg: Message) -> [SideEffect<Message>]
}

struct State: Component {

var something: String?

enum Message {

case downloadSomething
case receiveResponse(String)
}

mutating func send(msg: Message) -> [SideEffect<Message>] {
switch msg {
case .downloadSomething:
return [.sendRequest(Message.receiveResponse)]
case .receiveResponse(let response):
something = response
return []
}
}
}

因此状态由 State 建模你可以通过发送 Message 来更改它秒。如果有任何副作用需要计算,它们将作为 SideEffect 返回消息并将由其他人处理。每个SideEffect消息接受一个“回调”参数,一个 Message副作用完成后发送。这很好用。

现在,如果我想要一个通用的副作用消息怎么办?我想要这样的东西:

struct Request<ReturnType> { … }

并且有一个相关的副作用来加载请求并返回一个 ReturnType 类型的值:

enum SideEffect<Message> {
case sendRequest(Request<T>, (T) -> Message)
}

但这(显然)不能编译,因为 case必须在 T 上通用.我做不到整个SideEffect泛型超过 T ,因为还有其他与 T 无关的副作用.

我能以某种方式创建一个 SideEffect 吗?带有 Request<T> 的消息稍后会发送 MessageT ? (我想我想要类似 this feature discussed on swift-evolution 的东西。)

最佳答案

您需要输入删除 T – 通常这可以通过闭包来完成,因为它们可以从创建它们的站点引用上下文,而无需将该上下文暴露给外界。

例如,使用模拟 Request<T> (假设它是一个异步操作):

struct Request<T> {

var mock: T

func doRequest(_ completion: @escaping (T) -> Void) {
// ...
completion(mock)
}
}

我们可以构建一个 RequestSideEffect<Message>包含一个闭包,该闭包接受给定的 (Message) -> Void回调,然后对捕获的 Request<T> 执行请求例如,通过 (T) -> Message 转发结果,然后可以将其结果传递回回调(从而将类型变量 T “包含”在闭包中):

struct RequestSideEffect<Message> {

private let _doRequest: (@escaping (Message) -> Void) -> Void

init<T>(request: Request<T>, nextMessage: @escaping (T) -> Message) {
self._doRequest = { callback in
request.doRequest {
callback(nextMessage($0))
}
}
}

func doRequest(_ completion: @escaping (Message) -> Void) {
_doRequest(completion)
}
}

现在您的 SideEffect<Message>可以看起来像这样:

enum SideEffect<Message> {
case sendRequest(RequestSideEffect<Message>)
}

你可以实现State像这样:

protocol Component {
associatedtype Message
mutating func send(msg: Message) -> [SideEffect<Message>]
}

struct State: Component {

var something: String

enum Message {
case downloadSomething
case receiveResponse(String)
}

mutating func send(msg: Message) -> [SideEffect<Message>] {
switch msg {
case .downloadSomething:
let sideEffect = RequestSideEffect(
request: Request(mock: "foo"), nextMessage: Message.receiveResponse
)
return [.sendRequest(sideEffect)]
case .receiveResponse(let response):
something = response
return []
}
}
}

var s = State(something: "hello")
let sideEffects = s.send(msg: .downloadSomething)

for case .sendRequest(let sideEffect) in sideEffects {
sideEffect.doRequest {
_ = s.send(msg: $0) // no side effects expected
print(s) // State(something: "foo")
}
}

关于swift - 基于消息的体系结构中的通用消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46250924/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com