How to declare a block with arguments in swift?
Solution 1
The equivalent of Objective-C blocks are swift closures, so it would go as follows
{ (user: PFUser, error: NSError) in
if (!user) {
println("Uh oh. The user cancelled the Facebook login.");
} else if (user.isNew) {
println("User signed up and logged in through Facebook!");
} else {
println("User logged in through Facebook!");
}
}
Solution 2
You have many ways offered to pass a block equivalent to function in Swift.
I found three.
To understand this I suggest you to test in playground this little piece of code.
func test(function:String -> String) -> String
{
return function("test")
}
func funcStyle(s:String) -> String
{
return "FUNC__" + s + "__FUNC"
}
let resultFunc = test(funcStyle)
let blockStyle:(String) -> String = {s in return "BLOCK__" + s + "__BLOCK"}
let resultBlock = test(blockStyle)
let resultAnon = test({(s:String) -> String in return "ANON_" + s + "__ANON" })
println(resultFunc)
println(resultBlock)
println(resultAnon)
Update: There are 2 special cases to the Anonymous function.
The first is that function signature can be inferred so you don't have to rewrite it.
let resultShortAnon = test({return "ANON_" + $0 + "__ANON" })
The second special case works only if the block is the last argument, it's called trailing closure
Here is an example (merged with inferred signature to show Swift power)
let resultTrailingClosure = test { return "TRAILCLOS_" + $0 + "__TRAILCLOS" }
Finally:
Using all this power what I'd do is mixing trailing closure and type inference (with naming for readability)
PFFacebookUtils.logInWithPermissions(permissions) {
user, error in
if (!user) {
println("Uh oh. The user cancelled the Facebook login.")
} else if (user.isNew) {
println("User signed up and logged in through Facebook!")
} else {
println("User logged in through Facebook!")
}
}
IMO it's more beautiful than in ObjC
Solution 3
See if this works for you. It's crazy trying to learn this on day two.
let afterSignInAttempt: (PFUser?, NSError) -> Void = { user, error in
if(!user){
NSLog("Uh oh.")
} else {
user.isNew ? NSLog("Signed up") : NSLog("User Logged in")
}
}
Solution 4
If you want to store block in a variable and call it later, check this answer
Solution 5
Critically, if user
can be nil
then it must be declared as an Optional. Thus:
{ (user: PFUser?, error: NSError) -> {} in
if (nil == user) ...
}
noting that the type for user
includes ?
to indicate that user
is an optional argument (either nil
or of type PFUser
).
Other answers, that don't use an Optional, won't even compile.
Brandon Foo
Updated on July 01, 2020Comments
-
Brandon Foo almost 4 years
Having a hard time figuring out how to properly declare/use blocks with swift. What would be the swift equivalent of the following code?
Thanks.
^(PFUser *user, NSError *error) { if (!user) { NSLog(@"Uh oh. The user cancelled the Facebook login."); } else if (user.isNew) { NSLog(@"User signed up and logged in through Facebook!"); } else { NSLog(@"User logged in through Facebook!"); }
-
Fattie almost 10 yearsHey @Fran .. you may be able to provide a more up-to-date answer to THIS question ... stackoverflow.com/a/20760583/294884 thanks! you're pretty much it for "expert in SWIFT blocks..." :)
-
Francescu almost 10 yearsThanks you. I'll send this answer just for information even if the question is for objC.
-
holex almost 9 years...and IMHO, if you'd used the
__FUNCTION__
that would have been more beautiful.