在将函数作为参数传递时,我很难理解如何使用闭包来处理已完成的事件。
这是一个非常人为的例子:
class MessageService {
func sendMessage(s: String) {
print(s)
}
var messenger: Messenger {
createMessenger(completion: sendMessage(s:))
}
}
func createMessenger(completion: @escaping (String) -> Void) -> Messenger {
return Messenger { completion("This is a hardcoded message.") }
}
struct Messenger {
let sendMessage: () -> Void
init(sendMessage: @escaping () -> Void) {
self.sendMessage = sendMessage
}
}
let service = MessageService()
let messenger = service.messenger
messenger.sendMessage()
我想找出sendMessage
完成的时间(例如,它正在执行类似网络请求的操作),因此有一种方法可以为sendMessage
设置完成处理程序,以便我可以按照以下方式写东西:
messenger.sendMessage {
print("I finished sending a message!")
}
我尝试在服务类中添加这样的完成处理程序:
func sendMessage(s: String, completion: @escaping () -> Void) {
MessageRequest(with: s) {
completion()
}
}
但是,当我尝试使用createMessenger
方法时,事情开始变得非常混乱,因为上述函数具有某种疯狂的类型(String, () -> ()) -> ()
,我不知道如何处理。任何帮助将不胜感激,谢谢。
答案 0 :(得分:1)
因此,听起来您想要的是一个任意Messenger类型,其创建者告诉它要执行什么操作,完成该操作后,它将调用其调用者的完成处理程序。
如果您使用带有描述性名称的typealias
来跟踪所有闭包,则将很有帮助。而且,如果您不介意,我会更一般地将其命名为Agent
:
struct Agent {
typealias Completion = () -> Void
typealias Action = (Completion) -> Void
private let action: Action
static func create(action: @escaping Action) -> Agent {
Agent(action: action)
}
func execute(_ completion: @escaping Completion) {
action(completion)
}
}
因此,Agent
可以通过任意操作来创建,该操作接受完成处理程序以发出完成信号:
let agent = Agent.create { completion in
print("started executing action")
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { completion() }
}
agent.execute { print("done") }
现在,您可以使其适应您的MessengerService
类:
class MessageService {
func sendMessage(s: String) {
print(s)
}
var messenger: Agent {
Agent.create { completion in
sendMessage("This is a hardcoded message.")
completion()
}
}
}