2015-09-22 12 views
6

युक्त हमारे कोडबेस को स्विफ्ट 2 में अपग्रेड करने के बाद मुझे असामान्य समस्या का सामना करना पड़ा है। सेट अनुमानित नहीं है और न ही उम्मीद के अनुसार संघटन है।स्विफ्ट 2.0 एनएसओब्जेक्ट सबक्लास

class A: NSObject { 
    let h: Int 

    init(h: Int) { 
     self.h = h 
    } 

    override var hashValue: Int { 
     return h 
    } 
} 

func ==(lhs: A, rhs: A) -> Bool { 
    return lhs.hashValue == rhs.hashValue 
} 

let a = A(h: 1) 
let b = A(h: 1) 

var sa = Set([a]) 
let sb = Set([b]) 

sa.subtract(sb).count // Swift1.2 prints 0, Swift 2 prints 1 

sa.contains(a) // Swift1.2 true, Swift 2 true 
sa.contains(b) // Swift1.2 true, Swift 2 false 

ऐसा लगता है कि नया सेट आंतरिक संचालन के लिए हैशवैल्यू का उपयोग नहीं कर रहा है। कोई विचार यह है कि एक बग, या इस मुद्दे को हल करने का एक तरीका है?

उत्तर

11

मैंने आपके कोड के साथ थोड़ा सा खेला।

class A: Hashable { 
    let h: Int 

    init(h: Int) { 
     self.h = h 
    } 

    var hashValue: Int { 
     return h 
    } 

} 

func ==(lhs: A, rhs: A) -> Bool { 
    return lhs.hashValue == rhs.hashValue 
} 

let a = A(h: 1) 
let b = A(h: 1) 

var sa = Set([a]) 
let sb = Set([b]) 

sa.subtract(sb).count // Swift1.2 prints 0, Swift 2 prints 1 

sa.contains(a) // Swift1.2 true, Swift 2 true 
sa.contains(b) // Swift1.2 true, Swift 2 false 

a.hashValue == b.hashValue 

जब आप NSObject से इनहेरिट किए गए थे, अपने == अधिभार वास्तव में क्रियान्वित किया जा रहा नहीं कर रहा था: मैं यह नहीं रह गया है NSObject उपवर्गीकरण, लेकिन इसके बजाय Hashable प्रोटोकॉल के अनुरूप द्वारा काम कर पाने में सक्षम था। आप इस NSObject साथ काम करना चाहते हैं, तो आप isEquals ओवरराइड करने के लिए होगा:

override func isEqual(object: AnyObject?) -> Bool { 
    if let object = object as? A { 
     return object.h == self.h 
    } else { 
     return false 
    } 
} 
+0

धन्यवाद! मुझे यह समस्या एमकेएनोटेशन सबक्लास (जिसे एनएसओब्जेक्ट का विस्तार करने की भी आवश्यकता है) के साथ समस्या हो रही थी। क्या आपके पास इस विषय पर कुछ दस्तावेज का लिंक है? – brki

+1

स्विफ्ट 3 –

2
//: Playground - noun: a place where people can play 

import Foundation 

class X: NSObject { 
    var x:String 
    var y:Int 

    init(x:String, y:Int) { 
     self.x = x 
     self.y = y 
     super.init() 
    } 

    override var hashValue: Int { 
     return x.hashValue^y.hashValue 
    } 

    override func isEqual(object: AnyObject?) -> Bool { 
     if let rhs = object as? X { 
      return x == rhs.x && y == rhs.y 
     } else { 
      return false 
     } 
    } 
} 

func == (lhs:X, rhs:X) -> Bool { 
    return lhs.isEqual(rhs) 
} 

let x = X(x: "x1", y: 1) 
let y = X(x: "x1", y: 1) 
X(x: "x1", y: 1) == X(x: "x1", y: 1) // Swift 'x == y' (true) 
x.isEqual(y)       // Obj-C '[x isEqual: y]' (true) 

var s:Set<X> = [X(x: "x1", y: 1)] 
s.count // count == 1 
s.insert(X(x: "x2", y: 1)) 
s.count // count == 2 
s.insert(X(x: "x1", y: 1)) 
s.count // count == 2 
s.insert(X(x: "x2", y: 1)) 
s.count // count == 2 

मैं समय बिताया इस के लिए सही जवाब की तलाश में जब तक मैं इस प्रश्न/उत्तर मारा। क्या हो रहा था यह देखने के लिए मैं एक्सकोड प्लेग्राउंड में मूलभूत बातें लौटा था। स्विफ्ट Set में NSObject के उप-वर्गों का उपयोग करके अधिक पठनीय कोड का एक समूह बन जाता है।

+0

में एनएसओब्जेक्ट के साथ सही ढंग से सेट करने के लिए दोनों एक्वाल और हैशवैल्यू की आवश्यकता है, मुझे नहीं पता कि इतने सारे लोगों ने अन्य जवाब क्यों चुना। मेरे लिए, यह एक मूल्यवान और सही है। आपका बहुत बहुत धन्यवाद। –

+0

बस उल्लेख करने के लिए, 'NSObjectProtocol' में यह आवश्यक है, यदि आप' func isEqual (_ ऑब्जेक्ट: कोई?) -> बूल 'ओवरराइड करते हैं, तो आपको' var हैश: Int {get} 'को ओवरराइड करना होगा। दस्तावेज़ों में, यह कहता है 'यदि दो वस्तुएं बराबर हैं (जैसा कि isEqual (_ :) विधि) द्वारा निर्धारित किया गया है, तो उनके पास एक ही हैश मान होना चाहिए। '। https://developer.apple.com/reference/objectivec/nsobjectprotocol/1418859-hash –

संबंधित मुद्दे