alex
alex

Reputation: 957

swift closure stored and access as a variable

I want to implement a callback in a swift project just like I used to do in Objective-C I need a variable of type closure. That closure should take as a parameter an object and return nothing.

var downloadCompleted: (MLBook) -> (Void)!

When I need to trigger the callback I do this:

if self.downloadCompleted {
   self.downloadCompleted(book)
}

The compiler complains with this error message:

 Type '(MLBook) -> (Void)!' does not conform to protocol 'BooleanType'

If I remove the if statement the compiler says:

Property 'self.downloadCompleted' not initialized

even though it's implicitly unwrapped.

When I try to get the callback:

BookStore.sharedInstance.downloadCompleted{(book: MLBook) -> () in
   println("Print if you got the callback")
}

I get this error message:

'(MLBook) -> ()' is not convertible to 'MLBook'

I'm more worried about the last error message as I'm not quite sure what it is trying to tell me.

Any help would be appreciated. Thanks

Upvotes: 6

Views: 12302

Answers (2)

GoZoner
GoZoner

Reputation: 70235

Here is your working example. You have a number of mistakes which the attached illustrates. Note I had the download() method return Bool so that the result can be see in this screen shot.

enter image description here

But, your use of an implicitly unwrapped optional (aka '!') is incorrect. Such an optional is used when the value may be nil but will be assigned at a known time and not changed (see Apple documentation for a description). Your downloadCompleted is a true optional (at least in your example use). Thus, better code, which turns out to be slightly simpler is:

enter image description here

Upvotes: 9

Shuo
Shuo

Reputation: 8937

2 mistakes. 1st, The whole type should be wrapped in (), then followed a ? or ! as a optional or implicit unwrapped optional. 2nd, you should check with nil, in swift, no implicit boolean conversion.

In your use case, you should use Optional instead of Implicit unwrapped. Because there is big chance that your property has a nil value. With IUO(Implicit unwrapped optional), you skip compiler warning and will get a runtime error.

import Foundation

class MLBook {
    var name = "name"
}

class A {
    var downloadCompleted: ((MLBook) -> Void)?

    func down(){
        var book = MLBook()
        if let cb = self.downloadCompleted {
            cb(book)
        }
    }  
}

var a = A()
a.downloadCompleted = {
    (book: MLBook) -> Void in
    println(book.name)
}

a.down()

Upvotes: 5

Related Questions