How to declare a block with arguments in swift?

30,819

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.

Share:
30,819
Brandon Foo
Author by

Brandon Foo

Updated on July 01, 2020

Comments

  • Brandon Foo
    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
    Fattie almost 10 years
    Hey @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
    Francescu almost 10 years
    Thanks you. I'll send this answer just for information even if the question is for objC.
  • holex
    holex almost 9 years
    ...and IMHO, if you'd used the __FUNCTION__ that would have been more beautiful.