Donc, ce que je veux, c'est une classe qui peut obtenir une fermeture qui lui est transmise dans une fonction, elle peut aussi à un moment donné vouloir ignorer cette fermeture. Comment puis-je vérifier si la variable de fermeture est définie et comment puis-je la supprimer lorsque j'en ai fini avec elle?
Impossible d'appeler '! =' Avec une liste d'arguments de type '(@lvalue (sucsess: Bool !, products: [AnyObject]!) -> ()?, NilLiteralConvertible)' Type '(sucsess: Bool !, products: [AnyObject ]!) -> ()? ' n'est pas conforme au protocole 'NilLiteralConvertible'
class someClass{
//typealias completionHandlerClosureType = (sucsess:Bool!, items:[AnyObject]!)->()
var completionHandler:(sucsess:Bool!, items:[AnyObject]!)->()?
var hitpoints = 100
var someset = ["oh no!","avenge me!"]
init(){}
func getHitFunc(impact:Int, passedCompletionsHandler:(sucsess:Bool!, items:[AnyObject]!)->()){
completionHandler = passedCompletionsHandler
hitpoints = hitpoints - impact
}
func checkIfDead{
if hitpoints<=0 { // The error received
if completionHandler != nil{// Cannot invoke '!=' with an argument list of type
//'(@lvalue (sucsess: Bool!, products: [AnyObject]!) -> ()?, NilLiteralConvertible)'
//run the handler if dead
completionHandler(sucsess: true, items: someset)
//do not run it again
completionHandler = nil //Type '(sucsess: Bool!, products: [AnyObject]!) -> ()?' does not conform to protocol 'NilLiteralConvertible'
}
}
else{
completionHandler = nil //Type '(sucsess: Bool!, products: [AnyObject]!) -> ()?' does not conform to protocol 'NilLiteralConvertible'
}
}
}
Vous devez mettre votre signature de fermeture entre parenthèses pour rendre la fermeture elle-même facultative. De la façon dont il est écrit maintenant, la fermeture retourne un Void (qui n'a pas vraiment de sens).
var completionHandler: ((sucsess:Bool!, items:[AnyObject]!)->())?
Quelques points de style et révisions de votre exemple de code:
// Capitalize class names so it's clear what's a class
class SomeClass {
// "success" has two "c"s
var completionHandler: ((success:Bool!, items:[AnyObject]!)->())?
var hitpoints = 100
var someset = ["oh no!","avenge me!"]
init() { }
func getHitFunc(impact:Int, passedCompletionsHandler:(success:Bool!, items:[AnyObject]!)->()){
completionHandler = passedCompletionsHandler
hitpoints = hitpoints - impact
}
// You were missing the argument list here:
func checkIfDead() {
if hitpoints <= 0 {
// Rather than checking to see if the completion handler exists, you can
// just call it using optional syntax like this:
completionHandler?(success: true, items: someset)
}
completionHandler = nil
}
}
Tout d'abord, dans votre déclaration du gestionnaire d'achèvement, vous devez déclarer le tout comme facultatif avec l'utilisation de parenthèses:
var completionHandler: ((_ success: Bool, _ items: [Any]?) -> ())?
Ou, peut-être mieux, vous pouvez remplacer cette dernière ()
avec Void
:
var completionHandler: ((_ success: Bool, _ items: [Any]?) -> Void)?
Notez également que je ne pense pas que vous vouliez rendre le Bool
facultatif (car si la fermeture existe, vous passez probablement toujours une valeur de success
de true
ou false
). De toute évidence, le tableau de items
pourrait bien être facultatif.
Quoi qu'il en soit, une fois terminé, vous devez simplement vous assurer de déballer cette option:
func checkIfDead() {
if hitpoints <= 0 {
completionHandler?(true, items)
}
completionHandler = nil
}
Ceci effectue la fermeture si et seulement si ce n'est pas nil
, évitant ainsi de vérifier explicitement si c'était nil
.
Pour ce que ça vaut, cela pourrait être un cas où votre typealias
pourrait rendre cela moins déroutant:
typealias CompletionHandlerClosureType = (_ success: Bool, _ items: [Any]?) -> Void
La propriété est alors simplement:
var completionHandler: CompletionHandlerClosureType?
La fonction qui prend ce completionHandler
comme paramètre facultatif pourrait faire:
func startSomeProcess(passedCompletionHandler: CompletionHandlerClosureType?) {
completionHandler = passedCompletionHandler
// do whatever else you want
}
puis la logique d'achèvement finale est inchangée:
func finishSomeProcess() {
completionHandler?(true, items)
completionHandler = nil
}
(Remarque, ce qui précède a été modifié pour Swift 3. Veuillez voir révision précédente de cette réponse si vous voulez voir Swift 2 rendus.)