Search code examples
swiftclosuresblock

optional closure and check if it is nil


So what I want to have is a class that may get a closure passed to it in a function, it may also at some point want to disregard a that closure. How can I check if the closure variable is set and hwo can I delete it when I am done with it?

Cannot invoke '!=' with an argument list of type '(@lvalue (sucsess: Bool!, products: [AnyObject]!) -> ()?, NilLiteralConvertible)' Type '(sucsess: Bool!, products: [AnyObject]!) -> ()?' does not conform to protocol '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'
        }
    }
}

Solution

  • You need to wrap your closure signature in parentheses to make the closure itself optional. The way it's written now, the closure returns an optional Void (which doesn't really make sense).

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

    Some style points and revisions to your example 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
        }
    }