如何测试`NSObject`是否具有可以设置的任意名称的属性?

时间:2018-01-11 11:47:25

标签: ios swift swift4 nsobject

我想从字典中实现模型的通用填充。我使用以下测试测试模型是否具有属性,但条件总是失败:

if (self.responds(to:(NSSelectorFromString(keyName)))){
    self.setValue(keyValue, forKey: key )
}

以下是一个示例代码:

import UIKit

class myModel: NSObject {    
    var userName: String = ""
    var phoneNumber: String = ""

    init(dict: Dictionary<String, Any>) {
        super.init()

        for (key, value) in dict {
            let keyName = key     
            let keyValue: String = String(describing: value)

            print("key \(key) value \(value)")

            if (self.responds(to:(NSSelectorFromString(keyName)))){
                self.setValue(keyValue, forKey: key )
            }
        }          
    }        
}

4 个答案:

答案 0 :(得分:10)

你差不多完成了。在NSObject类的顶部添加以下内容 - @objcMembers

如 -

import UIKit

@objcMembers

class myModel: NSObject { 

答案 1 :(得分:2)

这可以按预期工作(在游乐场测试):

import UIKit

class myModel: NSObject {
    @objc var userName: String = ""
    @objc var phoneNumber: String = ""

    init(dict: Dictionary<String, Any>) {
        super.init()

        for (key, value) in dict {
            let keyCapitalized = key.prefix(1).uppercased() + key.dropFirst()

            let keyName = "set\(keyCapitalized):"
            let keyValue: String = String(describing: value)

            print("key \(key) (selector: '\(keyName))' value \(value)")

            if self.responds(to: Selector(keyName)) {
                self.setValue(keyValue, forKey: key)
            }
        }
    }
}

let m = myModel(dict: ["userName" : "milan", "data" : "data"])
print(">>> \(m.userName)") // prints ">>> milan"
print(">>> \(m.phoneNumber)") // prints ">>> " (number was not provided, and data key was ignored)

只有两点。

首先,您需要将这些属性公开给ObjectiveC以使responds()起作用 - 因此我在两个属性上添加了@objc注释。

其次,测试是否可以设置名为userName的属性的正确选择器语法不是Selector("userName"),而是Selector("setUserName:")(您正在测试一个setter)。

答案 2 :(得分:0)

字典需要为其键和值提供类型。初始化程序中的内容太模糊了。

因为从字典中获取内容的结果可能为零,所以您需要提供一个默认值,即??

后发生的值
class MyModel: NSObject {

    var userName: String = ""
    var phoneNumber: String = ""

    init(dict: [String : String]) {
        self.userName = dict["userName"] ?? ""
        self.phoneNumber = dict["phoneNumber"] ?? ""
        super.init()
    }

}

答案 3 :(得分:0)

下面你可以从字典中设置模型值。

class MyModel {
    var userName: String?
    var phoneNumber: String?

    init(dict: [String:Any]?) {
        self.userName = dict?["username"] as? String
        self.phoneNumber = dict?["phonenumber"] as? String
    }
}

示例用法:

let myModel = MyModel(dict: ["username":"test","phonenumber":"1234567890"])