In Objective-C, I have a completion block class defined as:
File.h
typedef void (^MYCompletionBlock)(BOOL success, NSDictionary *result, NSError *error);
Then, in a Swift file, I try to use the completion block as follows:
Swift.swift
class MyClass: NSObject{
...
func MyFunction() -> Void {
...
objcMethod(param1, withCompletion: {(MYCompletionBlock) -> Void in
if (success){ // Error:"Use of unresolved identifier 'success'"
}
}
...
}
...
}
But, I keep getting an error: "Use of unresolved identifier 'success'".
I've tried the following as well:
objcMethod(param1, withCompletion: {(success:Bool, result: NSDictionary, error:NSError) -> Void in
if (success){ // Error:"Cannot convert value of type '(Bool, NSDictionary, NSError) -> Void' to expected argument type "MYCompletionBlock!"
}
}
Can somebody help me understand how to correctly specify a Obj-C completion block in Swift?
Given that your closure doesn't specify nullability qualifiers (where they almost certainly are optional), one can safely assume that your Objective-C API has not been audited for nullability. Thus, Swift will treat pointers as implicitly unwrapped optionals. Furthermore, nowadays the
NSDictionary
is mapped to a[NSObject : AnyObject]
Swift dictionary.Thus, it would be:
Or, as Kobi points out, you can let the compiler infer the types:
Note, you don't have to remember this yourself. You can leverage Xcode's code completion as you enter the code. So, type enough to match the method name and when it matches
objcMethod
, then hit enter:When you get to
MYCompletionBlock
, hit enter again, and it will show you the correct signature:If this Objective-C method was my own class, I would audit it for nullability. So, for example, let's assume the
param
is optional, the closure is required, and theresult
anderror
were optional, you might define it like so:And, if that was the case, your Swift code would call it like so:
Or, again, just let the compiler infer the types for you (but this time they'd be inferred as optionals that are not implicitly unwrapped):
You shouldn't specify types for the completion block parameters, as some types defer between Swift and Objective C (e.g.
BOOL
is actuallyObjCBool
in Swift). This should work: