James Lingo James Lingo - 4 months ago 14
Swift Question

Passing closure in Swift

I have a function that I've been using in my code, but I need to pass a completion handler to it now (so I can exit a dispatch_group). I didn't want it to effect the rest of my code so I tried changing the namespace from this:

func uploadRecordable<T: Recordable>(instanceConformingToRecordable: T, database: CKDatabase)


to this:

func uploadRecordable<T: Recordable>(instanceConformingToRecordable: T, database: CKDatabase, completionHandler: (())? = nil)


When I go to pass a closure to it like so:

cloud.uploadRecordable(testRecordable, database: database) {
dispatch_group_leave(forCloudToBeClearOfTestRecord)
}


I get this error:

Function produces expected type 'Void' (aka '()'); did you mean to call it with '()'?


I think that because the
completionHandler: (())?
argument has a default value of
nil
the compiler is confused by the closure, but when I tried this I still get same error:

cloud.uploadRecordable(testRecordable, database: database, completionHandler: {
dispatch_group_leave(forCloudToBeClearOfTestRecord)
})


I haven't passed a lot of closures, so I could be doing it wrong, but
(())?
has worked for me in the past... Also, if it makes any difference this is being called in my tests not my regular code.

Any help on what I'm missing here?

-EDIT-

After changing the closure argument to
(() -> ())?
I get this error:

Cannot invoke `uploadRecordable` with an argument list of type '(MockRecordable?, database: CKDatabase, completionHandler: (() -> ())?)'


The first two arguments have been working fine, but it doesn't like my closure still. Should I be putting something on the first line (e.g.
var in
) even though I'm not giving it any variables. Thanks in advance.

Rob Rob
Answer

In the function declaration, rather than declaring the parameter as completionHandler: (())?, you want completionHandler: (() -> Void)? or completionHandler: (() -> ())?.

Thus:

func uploadRecordable<T: Recordable>(instanceConformingToRecordable: T, database: CKDatabase, completionHandler: (() -> Void)? = nil) { ... }

Or

func uploadRecordable<T: Recordable>(instanceConformingToRecordable: T, database: CKDatabase, completionHandler: (() -> ())? = nil) { ... }