比较Any类型的两个属性

时间:2018-03-23 10:06:16

标签: ios swift

我正在尝试比较一个类的两个实例的属性。之前我用过这个,它工作正常:

override public func isEqual(_ object: Any?) -> Bool {
    if let rhs = object as? BankDataModel, self.accountHolderName == rhs.accountHolderName, self.accountNumber == rhs.accountNumber,
        self.accountHolderThirdPartyAccountOwner == rhs.accountHolderThirdPartyAccountOwner, self.bankName == rhs.bankName, self.bankRoutingNumber == rhs.bankRoutingNumber, self.bic == rhs.bic, self.iban == rhs.iban, self.directDebitStatus == rhs.directDebitStatus, self.sepaCreditorID == rhs.sepaCreditorID, self.sepaMandateID == rhs.sepaMandateID{
        return true
    }else{
        return false
    }
}

但是如果我想使用它,我必须再次为我的所有模型类写这个。我想要一个可以用于所有模型类的函数,所以我使用了Mirror结构并试过这样的事情:

 override public func isEqual(_ object: Any?) -> Bool {
    if let rhs = object as? BankDataModel{
        return compareTwoObjects(objectToCompare: rhs, objectSelf: self)
    }else{
        return false
    }
}

每个模型中重写的isEqual方法将从Helper类调用此方法,因此我可以在每个模型中使用它:

func compareTwoObjects(objectToCompare: Any, objectSelf: Any) -> Bool{
    let objectSelf2 = Mirror(reflecting: objectSelf)
    let objectToCompare2 = Mirror(reflecting: objectToCompare)
    var index = objectToCompare2.children.startIndex
    for attr in objectSelf2.children{
        let type1 = Mirror(reflecting: attr.value).subjectType
        print(type1)
        let type2 = Mirror(reflecting: objectToCompare2.children[index].value).subjectType
        print(type2)
        if type1 == type2{
            print("Equal")
            if attr.value as! type1 != objectToCompare2.children[index].value as! type2{
                return false
            } 
        }
        index = objectToCompare2.children.index(index, offsetBy: 1)
    }
    return true
}

大多数代码工作正常,当两个变量的类型相等时,print("Equal")总是执行。 问题是这一行:

if attr.value as! type1 != objectToCompare.children[index].value as! type2{
      return false
 }

我收到此错误消息:“使用未声明的类型”type1“”。 如果我不使用转换为type1和type2,我得到的错误是我不能使用==两个属性为“Any”的属性。 有没有办法将type1和type2字符串转换为实际数据类型?或者,对于我想要达到的目标,可能有更好的方法吗?

这是我的印刷品输出:

Optional<String> Optional<String> Equal Optional<String> Optional<String> Equal Optional<Bool> Optional<Bool> Equal String String Equal Optional<String> Optional<String> Equal String String Equal String String Equal Optional<DirectDebitStatus> Optional<DirectDebitStatus> Equal

我将不胜感激任何帮助!

2 个答案:

答案 0 :(得分:2)

Swift 4

我想您可能想要使用Equatable界面。有了它,你可以实现这样的目标:

extension BankDataModel: Equatable {
    static func == (lhs: BankDataModel, rhs: BankDataModel) -> Bool {
        return
            lhs.accountHolderName == rhs.accountHolderName &&
            lhs.accountNumber == rhs.accountNumber &&
            lhs.accountHolderThirdPartyAccountOwner == rhs.accountHolderThirdPartyAccountOwner
    }
}

注意:您可以使用其他&&子句扩展return语句,以增加“等于”#check。

然后,只要您放置此扩展程序,就可以使用BankDataModel运算符将两个==相互比较,如下所示:

let bankAModel: BankDataModel = // Some model
let bankBModel: BankDataModel = // Also some model

if bankAModel == bankBModel {
  // Do stuff
}

<强>扩展

我能想到的最好的情况是,您在Equatable上同时实施了HashableBankDataModel,以便在Equatable方面形成一个干净的比较方法(只比较哈希)。

这种方式可以使代码更易于维护和清理。另请参见separation of concerns模式。

答案 1 :(得分:1)

这可能是您正在寻找的内容,它会先将两个Any?对象首先投放到NSObject来比较。

    private func equalAny<BaseType: Equatable>(lhs: Any?, rhs: Any?, baseType: BaseType.Type) -> Bool {
    if (lhs == nil && rhs != nil) || (rhs == nil && lhs != nil) { return false }
    if lhs == nil && rhs == nil { return true }
    guard let lhsEquatable = lhs as? BaseType, let rhsEquatable = rhs as? BaseType else {
        return false
    }
    return lhsEquatable == rhsEquatable
}

确保使用NSObject作为基本类型。调用这样的方法:

equalAny(lhs: value, rhs: otherValue, baseType: NSObject.self)