Crystal
Crystal

Reputation: 29518

Bridging ObjC function to Swift fails

I'm confused on something. I have this code in a framework in ObjC.

handler:(void (^)(NSDictionary<NSString *, id> *replyMessage))handler;

I have a function in Swift that has a parameter of type

@escaping ([String: Any]) -> Void

and tries to pass it to the ObjC Framework function. The compiler complains and says cast to

guard let handler = handler as? (([String : Any]?) -> Void) else {
    return
}

Why is the compiler asking me to cast it to this other type with an optional dictionary? When I do so the cast fails because it's not of that type, but if I try passing in the function as is, the compiler won't let me and tells me I need to cast it.

Is there something wrong with my ObjC function in order to make Swift happier?

I tried putting _Nonnull in the declaration of the framework before NSDictionary which then the compiler said,

Nullability specific _Nonnull cannot be applied to non-pointer type 'NSDictionary..."

As an aside, with Swift 4.0, I listened to the compiler and forcecasted my handler function

handler as! (([String : Any]?) -> Void)

When I called the function that uses it and it used to work. Now in Xcode 9.3, I get a crash for this.

Upvotes: 0

Views: 84

Answers (1)

rmaddy
rmaddy

Reputation: 318924

The Objective-C block has a nullable parameter but your Swift closure has a non-optional (non-nullable) parameter. That's the problem.

Either make the Objective-C block have a non-nullable parameter or make the Swift closure have an optional parameter.

Either do:

handler:(void (^)(NSDictionary<NSString *, id> * _Nonnull replyMessage))handler;

or do:

@escaping ([String: Any]?) -> Void

Upvotes: 3

Related Questions