Swift 拡張機能を使用してオーバーロードされたメソッドを Objective-C クラスに追加すると、最初のメソッドしか呼び出されないように見え、実行時に予期しない動作やクラッシュが発生します。(Objective-C ではなく) Swift クラスの拡張機能は正しく機能します。これに対する回避策があるかどうかを確認し、これがバグであることを確認し、Apple に報告する必要があることを確認したいと思います。Swift がサポートしているのに対し、Objective-C はオーバーロードされたメソッドをサポートしていないことを考えると、この 2 つを混在させると問題が発生する可能性があると想像できます。
拡張機能を取得するクラスは、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") }
}
次に、文字列、int、およびオブジェクトを使用してオーバーロードされたメソッドを呼び出します。
var objClass = ObjClass()
objClass.log(10)
objClass.log("string")
objClass.log(objClass)
var swiftClass = SwiftClass()
swiftClass.log(10)
swiftClass.log("string")
swiftClass.log(objClass)
ObjClass の場合、すべてのメソッド呼び出しは Int32 型の最初のメソッドに対して行われます。COpaquePointerを使用すると、これがオブジェクト ポインターに関連していることがわかりますが、少し異なります。
ObjClass->Int32: 10
ObjClass->Int32: 1881422800
ObjClass->Int32: 1879122512
Swift クラスの Swift Extension は期待どおりに動作します。
SwiftClass->Int32: 10
SwiftClass->String: string
SwiftClass->ObjClass
うまくいけば、これはある時点でサポートされる可能性があります。それまでは、予期しない動作やクラッシュが発生するのではなく、コンパイル時に失敗するはずです。これに対して提案する回避策はありますか?
次のように、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") }
}
次に、への呼び出しは正常にobjClass.log(str)
機能しますが、への呼び出しはobjClass.log(10)
次のようになります。
main(1): EXC_BAD_ACCESS (code=1, address=0xa)