2014-12-06 19 views
2

我最近讀The Swift Programming Language document,這給我介紹擴展,所以我想實現這個代碼:失敗嘗試使用擴展 - 斯威夫特

extension SKTexture{ 
    var size: CGSize { 
     return self.size() 
    } 
} 

在相同的代碼之後,我嘗試訪問在SKTexture的屬性:

someTexture.size.width 

然而,當我運行應用程序,我得到一個EXC_BAD_ACCESS enter image description here

我也注意到,即使我不嘗試訪問無線網絡dth屬性通過我的新計算屬性,執行someTexture.size().width而不是someTexture.size.width,我得到這個錯誤。有人能解釋我做錯了什麼嗎?

回答

4

短的答案:

對於來自NSObject派生的類,它具有同名作爲現有Objective-C的方法替換該方法的迅捷性 。

你的情況

因此,

var size: CGSize { 
    return self.size() 
} 

遞歸調用自己,直到程序與堆棧溢出 (當然,這就是這個網站是爲:)中止。

如果您爲該屬性選擇不同的名稱,例如

var theSize: CGSize { 
    return self.size() 
} 

然後一切都很好。


龍答:

SKTextureNSObject一個子類。因此所有的Swift屬性都是 「與Objective-C兼容」。因此,編譯器會生成一個可以從Objective-C代碼調用的getter方法。 size屬性的getter方法是-size方法。所以你現在有兩個-size方法: 原來的SKTexture和第二個定義在你的Swift代碼。

如果你做同樣的在同一個項目中 定義,那麼你會得到一個連接器警告自己的Objective-C類:

實例方法「大小」類別從/用戶/ ... /main.o在/Users/.../MyClass.o

覆蓋從類 方法如果Objective-C類是在外部框架中定義的(如在你的情況) 接頭不會注意到衝突。

現在return self.size()調用生成的Objective-C getter方法,該方法依次調用擴展方法 。這導致「無限」遞歸併最終導致堆棧溢出。

這是由棧回溯,你可以用LLDB bt 命令得到證實時,該程序已崩潰:

 
* thread #1: tid = 0x3d2ef, 0x000000010fb15e01 libobjc.A.dylib`objc::DenseMapBase, unsigned long, true, objc::DenseMapInfo > >, DisguisedPtr, unsigned long, objc::DenseMapInfo >, true>::FindAndConstruct(DisguisedPtr const&) + 21, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x7fff51b9cfe8) 
    frame #0: 0x000000010fb15e01 libobjc.A.dylib`objc::DenseMapBase, unsigned long, true, objc::DenseMapInfo > >, DisguisedPtr, unsigned long, objc::DenseMapInfo >, true>::FindAndConstruct(DisguisedPtr const&) + 21 
    frame #1: 0x000000010fb13e14 libobjc.A.dylib`objc_object::sidetable_retain() + 94 
    * frame #2: 0x000000010d8674d9 cdtest2`ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize(self=0x00007fcceea020f0) + 25 at AppDelegate.swift:19 
    frame #3: 0x000000010d867542 cdtest2`@objc ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize + 34 at AppDelegate.swift:0 
    frame #4: 0x000000010d8674ed cdtest2`ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize(self=0x00007fcceea020f0) + 45 at AppDelegate.swift:19 
    frame #5: 0x000000010d867542 cdtest2`@objc ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize + 34 at AppDelegate.swift:0 
    frame #6: 0x000000010d8674ed cdtest2`ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize(self=0x00007fcceea020f0) + 45 at AppDelegate.swift:19 
    frame #7: 0x000000010d867542 cdtest2`@objc ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize + 34 at AppDelegate.swift:0 
    frame #8: 0x000000010d8674ed cdtest2`ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize(self=0x00007fcceea020f0) + 45 at AppDelegate.swift:19 
    ... 
    frame #149556: 0x000000010d8674ed cdtest2`ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize(self=0x00007fcceea020f0) + 45 at AppDelegate.swift:19 
    frame #149557: 0x000000010d867542 cdtest2`@objc ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize + 34 at AppDelegate.swift:0 
    frame #149558: 0x000000010d8694e0 cdtest2`cdtest2.AppDelegate.application (application=0x00007fccee8005a0, launchOptions=None, self=0x00007fccebc06410)(ObjectiveC.UIApplication, didFinishLaunchingWithOptions : Swift.Optional>) -> Swift.Bool + 112 at AppDelegate.swift:83 
    frame #149559: 0x000000010d8697b0 cdtest2`@objc cdtest2.AppDelegate.application (cdtest2.AppDelegate)(ObjectiveC.UIApplication, didFinishLaunchingWithOptions : Swift.Optional>) -> Swift.Bool + 560 at AppDelegate.swift:0 
    ... 
    frame #149572: 0x000000010d86bcaa cdtest2`main + 42 at AppDelegate.swift:0 
    frame #149573: 0x00000001102f0145 libdyld.dylib`start + 1 

這(希望)解釋也就是爲什麼這兩個someTexture.size().widthsomeTexture.size.width出現問題: 在這兩種情況下,都會調用自定義擴展方法。

+0

好的,非常感謝你!直到現在我還不知道這個LLDB欺騙者。我想這是我以前應該學會的東西...... – 2014-12-08 19:52:28