Swift Extension无法将重载方法添加到Objective-C类

时间:2022-09-07 07:37:37

If a Swift extension is used to add overloaded methods to an Objective-C class, it appears to only call the first method, producing unexpected behaviour or a crash at runtime. An Extension on a Swift class (as opposed to Objective-C) works correctly. I would like to establish if there's any workarounds to this and confirm that this is a bug that I should report to Apple. Given that Objective-C does not support overloaded methods while Swift does, I can imagine that mixing the two is a recipe for problems.

如果使用Swift扩展将重载方法添加到Objective-C类,它似乎只调用第一个方法,在运行时产生意外行为或崩溃。 Swift类的扩展(与Objective-C相对)可以正常工作。我想确定是否有任何解决方法,并确认这是一个我应该向Apple报告的错误。鉴于Objective-C不支持Swift的重载方法,我可以想象将两者混合是问题的一个方法。

The classes getting the extension are both empty except for the Objective-C class having an init function. ObjClass is declared within .h and .m files and imported using the Swift bridging header. The original SwiftClass is defined within the code sample along with the Swift extensions:

除了具有init函数的Objective-C类之外,获取扩展的类都是空的。 ObjClass在.h和.m文件中声明,并使用Swift桥接头导入。原始SwiftClass在代码示例中与Swift扩展一起定义:

extension ObjClass {
    func log(param: Int32)    { NSLog("ObjClass->Int32: " + String(param)) }
    func log(param: String)   { NSLog("ObjClass->String: " + param) }
    func log(param: ObjClass) { NSLog("ObjClass->ObjClass") }
}

class SwiftClass {
}

extension SwiftClass {
    func log(param: Int32)    { NSLog("SwiftClass->Int32: " + String(param)) }
    func log(param: String)   { NSLog("SwiftClass->String: " + param) }
    func log(param: ObjClass) { NSLog("SwiftClass->ObjClass") }
}

Now call the overloaded methods with a string, int and object:

现在用字符串,int和object调用重载的方法:

var objClass = ObjClass()
objClass.log(10)
objClass.log("string")
objClass.log(objClass)

var swiftClass = SwiftClass()
swiftClass.log(10)
swiftClass.log("string")
swiftClass.log(objClass)

For ObjClass, all the method calls are made to the first method with type Int32. Through use of COpaquePointer, I can see this is related to the object pointer but slightly different.

对于ObjClass,所有方法调用都是对类型为Int32的第一个方法进行的。通过使用COpaquePointer,我可以看到这与对象指针有关但略有不同。

ObjClass->Int32: 10
ObjClass->Int32: 1881422800
ObjClass->Int32: 1879122512

Swift Extension on a Swift class works as expected:

Swift类上的Swift扩展按预期工作:

SwiftClass->Int32: 10
SwiftClass->String: string
SwiftClass->ObjClass

Hopefully this can be supported at some point. Until then, I believe it should fail at compile time rather than give unexpected behaviour or a crash. Does anyone have a workaround to suggest for this?

希望在某些时候可以支持这一点。在那之前,我认为它应该在编译时失败,而不是出现意外行为或崩溃。有没有人有一个解决方法来建议这个?

I know it's calling the first method as if I swap the ObjClass extension methods, like so:

我知道它正在调用第一个方法,好像我交换了ObjClass扩展方法,如下所示:

extension ObjClass {
    func log(param: String)   { NSLog("ObjClass->String: " + param) }
    func log(param: Int32)    { NSLog("ObjClass->Int32: " + String(param)) }
    func log(param: ObjClass) { NSLog("ObjClass->ObjClass") }
}

Then the call to objClass.log(str) works fine but the call to objClass.log(10) produces:

然后对objClass.log(str)的调用工作正常,但对objClass.log(10)的调用产生:

main(1): EXC_BAD_ACCESS (code=1, address=0xa)

1 个解决方案

#1


7  

ObjC doesn't support method overloading. When you extend an ObjC class, the interface to your code is the ObjC runtime—even if you're calling your Swift code in that class from other Swift code—so your class' interface can't use features of Swift that aren't also present in ObjC.

ObjC不支持方法重载。当您扩展ObjC类时,代码的接口是ObjC运行时 - 即使您从其他Swift代码调用该类中的Swift代码 - 因此您的类'接口不能使用Swift的特性也出现在ObjC。

As you've noted, this should probably be a compile error. I'd recommend filing a bug about that, especially since you've already put together a handy test case.

正如您所指出的,这应该是编译错误。我建议提交一个关于它的错误,特别是因为你已经把一个方便的测试用例放在一起。

#1


7  

ObjC doesn't support method overloading. When you extend an ObjC class, the interface to your code is the ObjC runtime—even if you're calling your Swift code in that class from other Swift code—so your class' interface can't use features of Swift that aren't also present in ObjC.

ObjC不支持方法重载。当您扩展ObjC类时,代码的接口是ObjC运行时 - 即使您从其他Swift代码调用该类中的Swift代码 - 因此您的类'接口不能使用Swift的特性也出现在ObjC。

As you've noted, this should probably be a compile error. I'd recommend filing a bug about that, especially since you've already put together a handy test case.

正如您所指出的,这应该是编译错误。我建议提交一个关于它的错误,特别是因为你已经把一个方便的测试用例放在一起。