web-dev-qa-db-ja.com

Swift内のオブジェクトの2つのインスタンスを比較する

次のクラスが与えられた場合、2つのインスタンスのすべての値を互いに比較するにはどうすればよいですか?

// Client Object
//
class PLClient {
    var name = String()
    var id = String()
    var email = String()
    var mobile = String()
    var companyId = String()
    var companyName = String()

    convenience init (copyFrom: PLClient) {
        self.init()
        self.name =  copyFrom.name
        self.email = copyFrom.email
        self.mobile = copyFrom.mobile
        self.companyId = copyFrom.companyId
        self.companyName = copyFrom.companyName

    }

}

var clientOne = PLClient()

var clientTwo = PLClient(copyFrom: clientOne)

if clientOne == clientTwo {   // Binary operator "==" cannot be applied to two PLClient operands
    println("No changes made")
} else {
    println("Changes made. Updating server.")
}

この使用例は、サーバーからのデータを表示するアプリケーションです。データがオブジェクトに変換されると、オブジェクトのコピーが作成されます。ユーザーは、オブジェクトの1つの値を変更するさまざまなフィールドなどを編集できます。

更新された可能性のあるメインオブジェクトを、そのオブジェクトのコピーと比較する必要があります。オブジェクトが等しい(すべてのプロパティの値が同じ)場合、何も起こりません。いずれかの値が等しくない場合、アプリケーションは変更をサーバーに送信します。

コードサンプルに示すように、値が指定されていないため、==演算子は受け入れられません。 ===を使用しても、常に2つの別個のインスタンスになるため、望ましい結果は得られません。

12
Michael Voccola

クラスがEquatableプロトコルに準拠していることを示し、==演算子を実装します。

このようなもの:

class PLClient: Equatable 
{
    var name = String()
    var id = String()
    var email = String()
    var mobile = String()
    var companyId = String()
    var companyName = String()
    //The rest of your class code goes here

    public static func ==(lhs: PLClient, rhs: PLClient) -> Bool{
        return 
            lhs.name == rhs.name &&
            lhs.id == rhs.id &&
            lhs.email == rhs.email &&
            lhs.mobile == rhs.mobile &&
            lhs.companyId == rhs.companyId &&
            lhs.companyName == rhs.companyName
    }
}
36
Duncan C

Duncan Cの回答に基づいて、カスタムの方法で使用されていることを少し明確にした代替案を考え出しました。

// Client Object
//
class PLClient {
    var name = String()
    var id = String()
    var email = String()
    var mobile = String()
    var companyId = String()
    var companyName = String()

    convenience init (copyFrom: PLClient) {
        self.init()
        self.name = copyFrom.name
        self.email = copyFrom.email
        self.mobile = copyFrom.mobile
        self.companyId = copyFrom.companyId
        self.companyName = copyFrom.companyName   
    }

    func equals (compareTo:PLClient) -> Bool {
        return
            self.name == compareTo.name &&
            self.email == compareTo.email &&
            self.mobile == compareTo.mobile
    }

}

var clientOne = PLClient()
var clientTwo = PLClient(copyFrom: clientOne)

if clientOne.equals(clientTwo) {
    println("No changes made")
} else {
    println("Changes made. Updating server.")
}
7
Michael Voccola

keypathを使用してフィールドをループできます

私はこれをテストしていませんが、一般的な考え方はそこにあります。有効なフィールドのリストを提供し、すべての赤道を書く代わりにそれらをループします。つまり、@ duncan-cと同じですが、ループが含まれています。

何かのようなもの:

class PLClient:Equatable {
    var name = String()
    var id = String()
    var email = String()
    var mobile = String()
    var companyId = String()
    var companyName = String()

    public static func ==(lhs: PLClient, rhs: PLClient) -> Bool{
        let keys:[KeyPath<PLClient, String>] = [\.name, \.id, \.email, \.mobile, \.companyId, \.companyName]
        return keys.allSatisfy { lhs[keyPath: $0] == rhs[keyPath: $0] }
    }
}
0
Johnston