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)
returnsVoid
type as we know. AssigningVoid
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)
}