【问题标题】:Generic Class with NSObject inheritance, self.setValue(, forKey: ) not work具有 NSObject 继承的泛型类,self.setValue(, forKey:) 不起作用
【发布时间】:2018-03-08 12:39:49
【问题描述】:

我想使用 self.setValue(, forKey: ) 直接在NSObject 中设置值,这时候给我一个错误。 like that

2018-03-08 17:36:36.723485+0530 BaseProject[20631:312969] *** 由于未捕获的异常“NSUnknownKeyException”而终止应用程序,原因:“[<_ttgc11baseproject8datarootcs_4root_0x600000452840> setValue:forUndefinedKey:]: 此类不符合键数据的键值编码。'

当我使用像 var data: [T] = [] 这样的 Generic T 设置值时,应用程序崩溃了,我像 var data: [Root] = [] 这样设置类名,然后就可以正常工作了。

我的代码是

protocol AGMappable {
    init(with responseDict: [String: AnyObject])
}

我的模型类是

class Root: NSObject, AGMappable {
    var avatar: String = ""
    var id: Int = 0
    var first_name: String = ""
    var last_name: String = ""

    required init(with responseDict: [String: AnyObject]) {
        super.init()
        avatar = responseDict["avatar"] as? String ?? ""
    }
}

使用 setValue(,forKey:) 设置值

class DataRoot<T: AGMappable>: NSObject, AGMappable{
    var page: Int = 0
    var per_page: Int = 0
    var total: Int = 0
    var total_pages: Int = 0
    var data: [T] = []

    required init(with responseDict: [String: AnyObject]){
        super.init()
        if let datastr = responseDict["data"] as? [[String : AnyObject]] {
            var temp: [T] = []
            for v in datastr {
                temp.append(T(with: v as [String: AnyObject]))
            }
            self.setValue(temp, forKey: "data") // Here error
        }
    }
}

【问题讨论】:

  • 为了更好地理解问题尝试使用正确的方法并查看错误setValue(temp, forKey: #keyPath(data))

标签: ios swift generics nsobject


【解决方案1】:

setValue(_:forKey:) 只能与 @objc 属性一起使用,因为它依赖于只有 @objc 属性具有的运行时功能。 Swift 4 改变了类成员对 Objective-C 可用的方式:默认情况下它们不再可用,因此您需要将类声明为 @objcMembers,或者将 @objc 单独添加到您需要暴露给 Objective 的每个成员-C。

但是,在您的情况下,由于该类是通用类,因此该类无法导出到 Objective-C,因此您需要将 data 声明为 @objc var data: [T] = []dynamic var data: [T] = []

【讨论】:

    【解决方案2】:

    你可以这样重写

        let datastr = responseDict["data"] as? [[String : Any]]
        self.data = datastr?.map {
            T(with: $0)
        } ?? [T]()
    

    【讨论】:

    • 我的要求是使用 self.setValue(,forKey:) 赋值
    • 你可以使用keyPaths吗?像这样self[keyPath: \DataRoot.data] = temp
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-20
    • 1970-01-01
    • 1970-01-01
    • 2020-05-17
    • 1970-01-01
    相关资源
    最近更新 更多