Comment le nouveau langage de programmation Swift D'Apple traite-t-il les blocs et les requêtes asynchrones?

C. F. Page du site web d'Apple sur Swift: https://developer.apple.com/swift/

y a-t-il des blocages dans Swift comme dans objective-c? Comment sont-ils créés et appelé?

Comment faire une requête asynchrone dans Swift?

est-il facile de créer des fuites de mémoire liées aux blocs dans swift? Si oui, comment voulez-vous éviter?

23
demandé sur nicael 2014-06-03 06:55:27

3 réponses

L'équivalent Swift d'un bloc (objectif-)C est appelé une fermeture. Il y a un chapitre entier à leur sujet dans le livre du langage de programmation Swift.

selon le contexte où vous utilisez une fermeture, vous pouvez la déclarer/l'utiliser avec une syntaxe très concise. Par exemple, une méthode qui prend un handler d'achèvement dont la signature est (success: Bool, error: NSError) - > Void peut être appelée comme ceci:

someMethod(otherParameters: otherValues, completionHandler:{ success, error in
    if !success { NSLog("I am a leaf on the wind: %@", error) }
})

il y a aussi une fermeture arrière syntaxe qui se lit bien dans les cas où une fermeture fournit essentiellement le contrôle de flux. Et vous pouvez laisser tomber les noms de paramètres quand vous voulez être vraiment bref (à un certain coût de lisibilité, mais c'est d'accord dans certains cas évidents comme ci-dessous). Souvent, une déclaration return est implicite, aussi.

myArray.sort { "151910920" <  }
let squares = myArray.map { value in
    value * 2
}    

Swift lui-même n'a rien pour les requêtes asynchrones, donc vous utilisez L'API existante pour cela. Vous pouvez utiliser la syntaxe de fermeture suivante:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
    // do some async stuff
    NSOperationQueue.mainQueue().addOperationWithBlock {
        // do some main thread stuff stuff
    }
}

dans la plupart des cas, vous n'avez pas à vous soucier de créer des cycles de référence avec les fermetures Swift comme vous le faites avec les blocs ObjC. Pour le dire simplement, la sémantique de capture sont assez similaires pour "juste travailler" la façon dont vous le voulez pour la plupart des choses, mais assez différents que les modèles communs pour les utilisations de bloc/fermeture (par exemple expédition à l'arrière-plan/fil principal et de référence self propriétés de l') ne causent pas de cycles.

Les Cycles

sont encore possibles, mais, et il y a une solution pour eux. Cette réponse est déjà un peu longue, alors consultez cycles de référence forts pour les fermetures dans le docs pour l'explication complète.

28
répondu rickster 2014-06-03 04:10:57
Les blocs

de Swift sont appelés fermetures. Ils fonctionnent de la même que les blocs (mais sont plus souples, et qui opèrent dans plus d'endroits). Des cycles de référence sont possibles avec des fermetures dans Swift, et peuvent être évités avec des listes de capture de fermetures.

" Swift fournit une solution élégante à ce problème, connu sous le nom de closure capture list. Cependant, avant d'apprendre comment briser un cycle de référence fort avec une liste de capture de fermeture, il est utile de comprendre comment un tel cycle peut être causés",

Extrait De: Apple Inc. "Le Langage De Programmation Swift."iBooks. https://itun.es/us/jEUH0.l

8
répondu Ben Gottlieb 2014-06-03 03:09:51

comme je l'ai dit dans une autre question, vous avez offert de nombreuses façons de passer un bloc équivalent à fonctionner dans Swift.

j'en ai trouvé trois.

pour comprendre cela, je vous suggère de tester ce petit morceau de code dans la Cour de récré.

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 pour la fonction Anonymous.

la première est que la signature de la fonction peut être déduite de sorte que vous n'avez pas à la réécrire.

let resultShortAnon = test({return "ANON_" + "151910920" + "__ANON" })

le deuxième cas spécial ne fonctionne que si le bloc est le dernier argument, il est appelé Fermeture arrière

voici un exemple (fusionné avec la signature inférée pour montrer Swift power)

let resultTrailingClosure = test { return "TRAILCLOS_" + "151920920" + "__TRAILCLOS" }

enfin, à titre d'exemple:

en utilisant toute cette puissance, ce que je ferais, c'est mélanger la fermeture arrière et l'inférence de type (avec le nom 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!")
    }
}
3
répondu Francescu 2014-06-04 00:03:12