2014-09-30 16 views
39

Quindi quello che voglio è una classe che può ottenere una chiusura passata ad esso in una funzione, potrebbe anche a un certo punto voler ignorare una chiusura. Come posso verificare se la variabile di chiusura è impostata e hwo posso cancellarla quando ho finito?chiusura opzionale e verificare se è nil

non può invocare '=!' Con una lista di argomenti di tipo '(@lvalue (sucsess: Bool !, prodotti:! [ANYOBJECT]) ->() ?, NilLiteralConvertible)' Tipo '(sucsess : Bool !, prodotti: [AnyObject]!) ->()? ' non è conforme al protocollo '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' 
     } 
    } 
} 

risposta

38

È necessario avvolgere la firma di chiusura tra parentesi per rendere la chiusura in sé opzionale. Il modo in cui è scritto ora, la chiusura restituisce un vuoto opzionale (che non ha molto senso).

var completionHandler: ((sucsess:Bool!, items:[AnyObject]!)->())? 

Alcuni punti di stile e le revisioni al vostro codice di esempio:

// 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 
    } 
} 
39

In primo luogo, nella dichiarazione del gestore di completamento, è necessario dichiarare il tutto come optional con l'uso delle parentesi:

var completionHandler: ((_ success: Bool, _ items: [Any]?) ->())? 

Inoltre, nota, non credo che si intende effettuare il Bool opzionale (perché se esiste la chiusura, è presumibilmente sempre passare un success valore di true o false). Chiaramente, l'array di items potrebbe essere facoltativo.

In ogni caso, una volta fatto, si era appena assicurarsi di scartare che opzionali:

func checkIfDead() { 
    if hitpoints <= 0 { 
     completionHandler?(true, items) 
    } 
    completionHandler = nil 
} 

Esegue la chiusura se e solo se non è nil, evitando la necessità di controllare in modo esplicito se fosse nil .


Per quel che vale, questo potrebbe essere un caso in cui il vostro typealias potrebbe rendere questo meno confusione:

typealias CompletionHandlerClosureType = (_ success: Bool, _ items: [Any]?) ->() 

Poi la proprietà è semplicemente:

var completionHandler: CompletionHandlerClosureType? 

La funzione che prende questo completionHandler come parametro facoltativo potrebbe fare:

func startSomeProcess(passedCompletionHandler: CompletionHandlerClosureType?) { 
    completionHandler = passedCompletionHandler 
    // do whatever else you want 
} 

e quindi la logica conclusione finale è invariato:

func finishSomeProcess() { 
    completionHandler?(true, items) 
    completionHandler = nil 
} 

(nota, quanto sopra è stato modificato per Swift 3. Si prega di vedere previous revision di questa risposta, se si vuole vedere Swift 2 rendition.

+0

l'alias di tipo è la soluzione ideale – Yitzchak

Problemi correlati