Home > Mobile >  swift question about "@escaping" inside class
swift question about "@escaping" inside class

Time:12-07

I am a newbie and maybe this is a silly question but I need some help. I have this code like below but I wonder that should I remove "@escaping" inside the checkSignedIn function.

Class A{
    public func checkSignedIn(complete: @escaping (Bool) -> Void) {
        _ = Amplify.Auth.fetchAuthSession { (result) in
            do {
                let session = try result.get()
                complete(session.isSignedIn)
            } catch {
                 print("Fetch auth session failed with error - \(error)")
                complete(false)
           }
        }
    }

I imagine that using "@escaping" will escape the return value from closure if I assign complete() to a variable like below.

Class A{
    var complete: (() -> Void)?
    public func checkSignedIn(complete: @escaping (Bool) -> Void) {
        _ = Amplify.Auth.fetchAuthSession { (result) in
            do {
                let session = try result.get()
                self.complete = complete(session.isSignedIn)
            } catch {
                print("Fetch auth session failed with error - \(error)")
                self.complete = complete(false)
           }
        }
    }

Then I can call A.complete again.

Am I wrong? I appreciate it if you teach me about this.

CodePudding user response:

No, they won't be the same.

The complete: @escaping (Bool) -> Void defines this:

  • a function (or a callback) that takes 1 argument (Bool), and returns nothing (Void). It's an equivalent of function that looks like this:
    func complete(_ value: Bool) { } 
    
  • this function escapes the scope of the function it's passed to, as it runs asynchronously (that's @escaping keyword meaning)

And then this function is called with complete(session.isSignedIn), where session.isSignedIn is a boolean argument you pass in, just as function's definition states, and function returns nothing

The statement self.complete = complete(session.isSignedIn) won't compile:

  • You defined self.complete as (() -> Void) type - that is a function or callback that takes no arguments, and returns nothing. It's an equivalent of function:
    func y() { }
    
  • So complete(session.isSignedIn) returns Void type as we know. Assigning Void type to (() -> Void) type is not going to work.

If you want to save the escaping function / callback to be used elsewhere, you can do this:

// Make sure signature of the variable matches that of a function argument
var complete: ((Bool) -> Void)?

public func checkSignedIn(complete: @escaping (Bool) -> Void) {

    // Save callback at the start of the function
    self.complete = complete
    // Then continue to a asynch part of the code:
    _ = Amplify.Auth.fetchAuthSession { (result) in
        // Inside this callback, you still can use the function argument
        complete(session.isSignedIn)
    ...
}

// But in another function, you have to use self.complete, e.g.:
func x() {
    // Use saved callback. You don't have to say `self` here, just using it for clarity
    self.complete(true)
}
  • Related