简体   繁体   English

从 C# 中的 async/await 到 Swift 中的闭包

[英]From async/await in C# to Closures in Swift

Coming from a C# background with async/await mindset I'm having some troubles to understand how to use closures in Swift properly.来自具有 async/await 心态的 C# 背景,我在理解如何正确使用 Swift 中的闭包时遇到了一些麻烦。

I'm using the following method getMessagingId to get the firebase messaging ID.我正在使用以下方法getMessagingId来获取 firebase 消息传递 ID。 After I receive the ID via a closure I want to do something with the ID.在我通过闭包收到 ID 后,我想对 ID 做一些事情。 However, I simply don't know how to get that value out of InstanceID.instanceID().instanceID(...) so that I can use it in the methods processMessagingId() and registerMessagingId() later.但是,我只是不知道如何从InstanceID.instanceID().instanceID(...)获取该值,以便稍后在方法processMessagingId()registerMessagingId()使用它。 In C# I would use async/await to achieve that.在 C# 中,我会使用 async/await 来实现这一点。

// Register this device
public func registerThisDevice() {
    // get the messaging ID
    var messagingId = getMessagingId()

    // process this messaging ID
    processMessagingId(messagingId)

    // register this messaging ID
    registerMessagingId(messagingId)
}

// get the messaging ID for firebase messaging
func getMessagingId() -> String {
    InstanceID.instanceID().instanceID(handler: { (result, error) in
        if let error = error {
            print("Error fetching messaging id: \(error)")
        } else if let result = result {
            print("Messaging id is \(result.token)")
        }
    })
    return ""
}

handler is a completion handler that also uses @escaping keyword. handler是一个完成处理程序,它也使用@escaping关键字。

I read a couple of articles about completion handlers and also @escaping.我阅读了几篇关于完成处理程序和@escaping 的文章。 But I just can't wrap my head around this.但我就是无法解决这个问题。

When you're doing async calls, you need to wait until async call ends and after that you can work with received data.当您进行异步调用时,您需要等到异步调用结束,然后才能处理接收到的数据。 For this we're using completion handlers in Swift.为此,我们在 Swift 中使用完成处理程序。

Start with declaring completion parameter instead of having returning value从声明完成参数而不是返回值开始

func getMessagingId(completion: @escaping (String) -> ())

What does that means?那是什么意思?

Simplified, you declare what should happen when completion is called from this method.简而言之,您可以声明从该方法调用completion时应该发生的事情。 You want to pass parameter of type String which you can use in completion 's closure and then you want to call code inside completion 's closure您想传递可以在completion的闭包中使用的String类型的参数,然后您想在completion的闭包中调用代码

So now let's call our completion and as parameter let's pass our message所以现在让我们调用我们的completion并作为参数让我们传递我们的消息

if let error = error {
    completion("Error fetching messaging id: \(error)")
} else if let result = result {
    completion("Messaging id is \(result.token)")
}

Ok, now let's call our method好的,现在让我们调用我们的方法

getMessagingId { message in // here you give `String` parameter name
    print(message) // this code gets executed when you call `completion` in `getMessagingId`
}

Now once you're able to understand this, you can pass multiple parameters like for example success , error , messageId , whatever you need...现在,一旦您能够理解这一点,您就可以传递多个参数,例如successerrormessageId ,无论您需要什么...

You can use this framework for Swift coroutines - https://github.com/belozierov/SwiftCoroutine您可以将此框架用于 Swift 协程 - https://github.com/belozierov/SwiftCoroutine

When you call await it doesn't block the thread but only suspends coroutine, so you can use it in the main thread as well.当您调用 await 它不会阻塞线程而只会挂起协程,因此您也可以在主线程中使用它。

func awaitGetMessagingId() throws -> String {
    let (result, error) = try Coroutine.await {
        InstanceID.instanceID().instanceID(handler: $0)
    }
    if let error = error { throw error }
    return result ?? ""
}

and then call this method inside coroutine:然后在协程中调用这个方法:

DispatchQueue.main.startCoroutine {
    let id = try awaitGetMessagingId()
    print("Messaging id is \(id)")
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM