从Swift中调用名为`init`的Obj-C类方法

4

我在我的Swift 4.1代码中使用了一个第三方库,该库有一个名为init()的类级别方法的Obj-C头文件。当我尝试调用它时,编译器会混淆并表示我想要使用实例初始化程序还是这个静态初始化方法,如下所示:

My3rdPartyClass.init() // 错误:'init()'的使用不明确

My3rdPartyClass.h文件中:

@interface My3rdPartyClass : NSObject

+(void)init;

@end

2
“该库有一个Obj-C头文件,其中包含一个名为init()的类级方法。”好吧,那是非法的。你不能从Swift调用该方法;你必须在Objective-C中编写一个跳板函数。(假设您无法更改源代码。)请谴责这个库的开发者。 - matt
2
在Swift 4.2中,您应该能够说My3rdPartyClass.\init`(),以便告诉Swift“是的,我指的是标识符”(如果我没记错,Swift 4.2是第一个正确区分初始化程序和名为init`的静态成员的版本,因此在4.1中无法使用)。但是,是的,这是一个糟糕的API。 - Hamish
@Hamish:确实,我没有注意到。请将其发布为答案。 - Martin R
@MartinR 如果您愿意将其包含在您的答案中,我会很高兴 - 否则我担心我会重复您已经提出的所有观点(而且由于OP说他们正在使用4.1,4.2的解决方案似乎不是直接的答案)。 - Hamish
@Hamish:那个“反引号技巧”对于工厂初始化器也适用吗?我无法弄清如何在https://stackoverflow.com/q/53704499/1187415中应用它。 - Martin R
1
@MartinR 我不这么认为,因为工厂方法是作为初始化器导入的,而不是命名为init的静态成员。无论如何,OP在那个问答中得到的行为都是一个错误。 - Hamish
1个回答

5
在Swift 4.1及以前版本中,这种歧义出现在类方法中,因为:
+ (void)init;

NSObject的初始化方法

- (instancetype)init

在Swift中,可以使用My3rdPartyClass.init()来调用这些类。可能的解决方案有:

  • Rename the Objective-C class method.
  • Annotate the function declaration with a different Swift name:

    +(void)init NS_SWIFT_NAME(classInit());
    

    That leaves the Objective-C interface unchanged, but the function can be called from Swift as

    OClass.classInit()
    
  • If no modification of the Objective-C header file is possible then you can still call the function from Swift as

    My3rdPartyClass.init() as Void
    

    The Void return type resolves the ambiguity.

Swift 4.2 (Xcode 10)开始,您可以这样调用类方法:

OClass.`init`()

没有对Objective-C API做任何更改(归功于@Hamish)。反引号告诉编译器,你想要成员函数而不是初始化程序。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接