I simply created an Objective-C base class and implemented my existing code!
You don’t need to use Objective-C here, you just need to inherit from
NSObject
. For example:
class Person: NSObject {
convenience init(properties: [String:Any]) {
self.init()
for (k, v) in properties {
if self.responds(to: setterForKey(k)) {
self.setValue(v, forKey: k)
}
}
}
@objc dynamic var name: String = ""
@objc dynamic var age: Int = 0
}
func setterForKey(_ key: String) -> Selector {
let sel = "set\(String(key.first!).uppercased())\(key.dropFirst()):"
return Selector(sel)
}
let p = Person(properties: ["name": "Quinn", "fullName": "unknown"])
print(p.name, p.age) // -> Quinn 0
Note If you’re going all in on Objective-C dynamism, you should make sure to declare your properties
dynamic
. This ensures that references to the property always go through the Objective-C runtime. You can think of it as an extension to
@objc
.
@objc
means that references can be made via the Objective-C runtime;
dynamic
means that they
must be made that way.
[I’m] somewhat disappointed that Apple's bold new "modern" language isn't even as capable as Objective-C.
Well, I hope the answers on this thread have reassured you that Swift is at least as capable as Objective-C in this regard. However, I want to step back and discuss the big picture some more.
From the discussion here it should be clear that Swift leans heavily on the Objective-C runtime for its dynamic features. This is not an accident. Swift must interoperate with Apple frameworks, and Apple frameworks have a long history of using Objective-C for dynamism.
Swift’s native dynamism story is only just beginning. This is important because the current approach, relying on Objective-C, only works an Apple platforms. All those Swift-on-server folks miss out )-:
However, you have to understand that one of Swift’s main goals is safety, and there’s often a tradeoff between dynamism and safety. Many of the best features of Swift allow you to do dynamic things in a safe way. For example, in Objective-C you might use dynamic features to decode JSON, but in Swift you can do that using
Codable
:
struct Person: Codable {
var name: String
var age: Int?
}
let jsonData = try JSONSerialization.data(withJSONObject: [
"name": "Quinn",
"fullName": "unknown"
], options: [])
let p = try JSONDecoder().decode(Person.self, from: jsonData)
print(p.name, p.age) // -> Quinn nil
The nice thing about this is that it’s type safe. The decoder will fail if
name
is not a string, or is missing (because the
name
property is not optional).
If your a fan of dynamism then I encourage you to explore this and other dynamic features in Swift, including:
And this is definitely not the end of the story. For example, Swift’s current reflection support is a known problem and there’s lots of enthusiasm for addressing that. If you want to get involved in these developments, hop on over to Swift Evolution.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"