Avoir du mal à comprendre comment déclarer/utiliser correctement des blocs avec Swift. Quel serait l'équivalent Swift du code suivant?
Merci.
^(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!");
}
L'équivalent des blocs Objective-C sont les fermetures Swift, donc ça irait comme suit
{ (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!");
}
}
Vous avez plusieurs possibilités pour passer un bloc équivalent à fonctionner dans Swift.
J'ai trouvé trois.
Pour comprendre cela, je vous suggère de tester dans le terrain de jeu ce petit morceau de 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)
Mise à jour: Il y a 2 cas spéciaux à la fonction Anonyme.
La première est que la signature de la fonction peut être déduite afin que vous n'ayez pas à la réécrire.
let resultShortAnon = test({return "ANON_" + $0 + "__ANON" })
Le deuxième cas spécial ne fonctionne que si le bloc est le dernier argument, il s'appelle fin de la fermeture
Voici un exemple (fusionné avec une signature inférée pour montrer la puissance Swift)
let resultTrailingClosure = test { return "TRAILCLOS_" + $0 + "__TRAILCLOS" }
Finalement:
En utilisant tout ce pouvoir, je mélangerais fin de clôture et inférence de type (avec nommage pour la lisibilité)
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!")
}
}
OMI c'est plus beau que dans ObjC
Si vous voulez stocker un bloc dans une variable et l'appeler plus tard, cochez cette answer
De manière critique, si user
peut être nil
, alors il doit être déclaré comme facultatif. Ainsi:
{ (user: PFUser?, error: NSError) -> {} in
if (nil == user) ...
}
notant que le type pour user
inclut ?
pour indiquer que user
est un argument optional (soit nil
ou de type PFUser
).
D'autres réponses, qui n'utilisent pas un optionnel, ne seront même pas compilées.
Voyez si cela fonctionne pour vous. C'est fou d'essayer d'apprendre cela le deuxième jour.
let afterSignInAttempt: (PFUser?, NSError) -> Void = { user, error in
if(!user){
NSLog("Uh oh.")
} else {
user.isNew ? NSLog("Signed up") : NSLog("User Logged in")
}
}
// Définissez-le
class IDDBlockTime {
// return time elapsed in milliseconds
//
static func timeSpent(_ block: (Void) -> Void) -> TimeInterval {
let methodStart = Date()
block()
return Date().timeIntervalSince(methodStart) * 1000.0
}
}
// utilise le
let timeSpent = IDDBlockTime.timeSpent {
// lines of code you want to measure
//
self.doSomethig()
}
print("timeSpent: '\(timeSpent) ms'")