1. 程式人生 > >Swift中自定義類==比較方法未被呼叫的分析和解決

Swift中自定義類==比較方法未被呼叫的分析和解決

在專案中自定義了2個類:A和B,其中A含有B的例項變數.

在這2個類中都定義了==比較方法,按照正常來說:比較A,必然比較B.因為需要比較A中型別為B的例項變數.

但實際執行中發現,兩個字面上完全一樣的A例項物件,比較竟然不相等!!!

在A的==方法中下斷點,發現3個問題:

  1. 比較不相等是因為其中B例項變數的比較不相等
  2. B例項比較並沒有呼叫B中的==比較方法
  3. 最為奇怪的是:在Xcode的lldb中手動輸入同樣的相等表示式,結果卻是相等的!

首先將A和B中的==的方法比較一下,並沒有什麼值得特別注意的地方.

但是有一點,A在專案本身中,而B卻在static lib中!!!

在B中的==方法是這樣寫的:

static func ==(lhs: HyDateRange, rhs: HyDateRange) -> Bool {
   if lhs.start == rhs.start,lhs.end == rhs.end{
        return true
    }
    return false
}

其中start和end都是Date型別.看出什麼問題了麼???

我可以負責任地說:就該方法實現本身來說,是沒有任何問題的!只是該方法可見域錯了!它必須要是public!!!

如果不是public,則不會被外界(App)呼叫!但在比較的時候的確呼叫了一個返回false的比較方法,那是什麼呢?我們再來看一下類B的定義:

@objc(Objc_B)
public class B:NSObject,NSCopying,NSCoding{

}

可以看到,B派生自NSObject類,而NSObject類是遵守Equatable協議的,這意味著該類為你隱式生成了一個==方法,而你之前呼叫的就是這個方法,可想而知該方法預設比較的是兩個例項的===(引用)比較,自然返回false!

那麼A的==方法為什麼不用寫public限定?因為前面說了A是在專案裡的,在同一專案中統統都可以訪問到,所以不用寫public字首.

所以前兩個問題的解決很簡單,就是在B類的==方法前面加上public限定!

現在還有第三個問題:為毛除錯裡相同相等判斷表示式的結果和App實際執行時的不一樣???

這個本貓只有猜測:App執行時其==方法是編譯時繫結(至少對於類的這個static方法來說是),而lldb除錯時是即時繫結,此時lldb在執行時可以"看到"原本不能"看到"的非public==方法,所以判斷結果是正確的.

以上純屬猜測,歡迎指正 ?

最後,感謝觀賞 ?