Given the following Objective-C methods
@import Foundation;
NS_ASSUME_NONNULL_BEGIN
@interface TestClass : NSObject
// Variant 1. Notice that arg1 is nullable, and that all closure arguments are nullable.
+ (void)test:(NSString *_Nullable)arg1
action:(nullable void (^)(void))action;
// Variant 2. Notice that arg2 is non null, there is an additional, nullable, closure argument
+ (void)test:(NSString *)title
action:(nullable void (^)(void))action
action2:(nullable void (^)(void))action2;
@end
NS_ASSUME_NONNULL_END
I find that when I attempt to call the first method from Swift with fully specified args, it actually calls the second variant when I use a trailing closure
// Calls first variant (This is an erroneous claim, hence Matt's answer)
TestClass.test("arg1", action: {})
// Calls second variant
TestClass.test("arg2") {}
I was expecting Variant 1 to be called in both cases. I'm unclear if I'm doing something wrong or not. I also seem to have missed the fact that Swift could provide generate arguments at all when calling Obj-C methods and am struggling to find the relevant documentation on it.
If I replace the Obj-C TestClass with the equivalent
class TestClass {
class func test(_ arg1: String?, action: (() -> ())? = nil) {
}
class func test(_ arg1: String!, action: (() -> ())? = nil, action2: (() -> ())? = nil) {
// Should not get here
assert(false)
}
}
Then I get a compiler warning about ambiguous use of 'test' in both calls.
Tested on Xcode 12.3 and 12.4.