ios - 来自 equatable 协议(protocol)的 func == 不适用于自定义对象,swift

标签 ios swift equatable

我的目标是显示历史登录(例如用户名)的用户列表(如果有的话)。为了做到这一点,我正在做

1. Create an custom object named User like below

 class User: NSObject
    {
        var login: String

        init(login: String)
        {
            self.login = login
        }
        required init(coder aDecoder: NSCoder) {
            login = aDecoder.decodeObjectForKey("login") as! String
        }

        func encodeWithCoder(aCoder: NSCoder) {
            aCoder.encodeObject(login, forKey: "login")
        }
    }

    // This conform to make sure that I compare the `login` of 2 Users
    func ==(lhs: User, rhs: User) -> Bool
    {
        return lhs.login == rhs.login
    }

在 UserManager 中,我正在保存检索 一个用户。在保存之前,我正在检查历史登录列表是否包含 User,否则我不会添加它。

class UserManager : NSObject
{
    static let sharedInstance   =   UserManager()
    var userDefaults            =   NSUserDefaults.standardUserDefaults()

    func saveUser(user:User)
    {
        var users = retrieveAllUsers()

        // Check before adding
        if !(users.contains(user))
        {
            users.append(user)
        }


        let encodedData =   NSKeyedArchiver.archivedDataWithRootObject(users)
        userDefaults.setObject(encodedData, forKey: "users")
        userDefaults.synchronize()
    }

    func retrieveAllUsers() -> [User]
    {
        guard let data  =   userDefaults.objectForKey("users") as? NSData else
        {
            return [User]()
        }
        let users   =   NSKeyedUnarchiver.unarchiveObjectWithData(data) as! [User]
        // Testing purpose
        for user in users
        {
            print(user.login)
        }
        return users
    }
}

我是第一次尝试

UserManager.sharedInstance.saveUser(User(login: "1234"))

现在它保存了第一次登录。第二次我也是

UserManager.sharedInstance.saveUser(User(login: "1234"))

UserManager 仍然将第二次登录添加到 nsuserdefault 中。这意味着函数 contains 失败并导致

func ==(lhs: User, rhs: User) -> Bool
{
    return lhs.login == rhs.login
}

无法正常工作。

有没有人知道为什么或对此有任何想法。

最佳答案

问题是 User 派生自 NSObject。这意味着(正如您所说的那样)永远不会咨询您的 == 实现。对于从 NSObject 派生的对象,Swift 的行为是不同的;它以 Objective-C 的方式做事。要在派生自 NSObject 的对象上实现等同性,请覆盖 isEqual:。这就是使 NSObject 派生对象在 Objective-C 和 Swift 中以自定义方式相等的原因。

只需将这段代码直接粘贴到您的用户类声明中,contains 就会按照您的意愿开始工作:

override func isEqual(object: AnyObject?) -> Bool {
    if let other = object as? User {
        if other.login == self.login {
            return true
        }
    }
    return false
}

关于ios - 来自 equatable 协议(protocol)的 func == 不适用于自定义对象,swift,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38384124/

相关文章:

ios - 我在创建一个单例吗?

ios - 使用标签创建 UIImageView。 swift 3

android - 为任何移动设备编译时不推荐使用 TList

ios - 在基于标签栏的应用程序上添加导航栏

ios - sceneView.delegate 和 sceneView.session.delegate 有什么区别?

flutter - 为什么我收到 Equatable 错误 : The element type can't be assigned to the list type 'Object'

ios - CoreBluetooth 连接设置时间变化很大

ios - 如何使用 BoltsSwift 更好地链接任务?

ios - 符合 Equatable for Diffing 的协议(protocol)