Reputation: 1100
I want to implement a generic populating of a model from a dictionary. I test if the model has a property using a following test, but the condition always fails:
if (self.responds(to:(NSSelectorFromString(keyName)))){
self.setValue(keyValue, forKey: key )
}
Here is an example code:
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 )
}
}
}
}
Upvotes: 1
Views: 756
Reputation: 1318
You are almost done. Add the following at top of your NSObject class - @objcMembers
Such as -
import UIKit
@objcMembers
class myModel: NSObject {
Upvotes: 4
Reputation: 19737
This works as you expect (tested in playgrounds):
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)
Just two points.
First of all, you need to expose those properties to ObjectiveC for responds()
to work - therefore I added @objc
annotations on both properties.
Second of all, the proper selector syntax to test if you can set the property named userName
is NOT Selector("userName")
, but Selector("setUserName:")
(you are testing a setter).
Upvotes: 2
Reputation: 1593
Below way you can set model values from a dictionary.
class MyModel {
var userName: String?
var phoneNumber: String?
init(dict: [String:Any]?) {
self.userName = dict?["username"] as? String
self.phoneNumber = dict?["phonenumber"] as? String
}
}
Example Usage :
let myModel = MyModel(dict: ["username":"test","phonenumber":"1234567890"])
Upvotes: 0
Reputation: 1712
Dictionaries need to be given a type for their keys and values. What you have in your initialiser is too ambiguous.
Because the result of getting something out of a dictionary can be nil, you need to provide a default value which is what happens after ??
class MyModel: NSObject {
var userName: String = ""
var phoneNumber: String = ""
init(dict: [String : String]) {
self.userName = dict["userName"] ?? ""
self.phoneNumber = dict["phoneNumber"] ?? ""
super.init()
}
}
Upvotes: 0