具有 NSObject 继承的泛型类,self.setValue(, forKey:) 不起作用

Posted

技术标签:

【中文标题】具有 NSObject 继承的泛型类,self.setValue(, forKey:) 不起作用【英文标题】:Generic Class with NSObject inheritance, self.setValue(, forKey: ) not work 【发布时间】: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)) 【参考方案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

以上是关于具有 NSObject 继承的泛型类,self.setValue(, forKey:) 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

java 定义泛型类的问题

java中接口具有泛型,继承的时候该怎么处理

Java泛型类继承实现

Java中的泛型的问题?

Java 泛型泛型简介 ( 泛型类 | 泛型方法 | 静态方法的泛型 | 泛型类与泛型方法完整示例 )

17.scala的泛型类