通过在Swift中订阅访问属性
我在Swift中有一个自定义类,我想使用订阅来访问它的属性,这可能吗 我想要的是这样的东西:通过在Swift中订阅访问属性,swift,swift-playground,Swift,Swift Playground,我在Swift中有一个自定义类,我想使用订阅来访问它的属性,这可能吗 我想要的是这样的东西: class User { var name: String var title: String subscript(key: String) -> String { // Something here return // Return the property that matches the key… } init(na
class User {
var name: String
var title: String
subscript(key: String) -> String {
// Something here
return // Return the property that matches the key…
}
init(name: String, title: String) {
self.name = name
self.title = title
}
}
myUser = User(name: "Bob", title: "Superboss")
myUser["name"] // "Bob"
更新:我之所以要寻找它,是因为我使用HTML模板进行渲染。我希望能够将我的模型对象传递给GRMustache渲染器
GRMustach使用键控的订阅objectForKeyedSubscript:方法和键值编码valueForKey:方法获取值。任何兼容对象都可以为模板提供值
我想你可以做到:
class User {
let properties = Dictionary<String,String>()
subscript(key: String) -> String? {
return properties[key]
}
init(name: String, title: String) {
properties["name"] = name
properties["title"] = title
}
}
值得注意的是,Swift目前似乎不支持按名称进行反射。reflect
函数返回一个Mirror
,其下标是基于Int
的,而不是基于String
。(此处为GRMustache作者)
在一个面向swift的Mustache库出现之前,我建议让您的类从NSObject继承(以便它们具有valueForKey:
方法)。GrMustach然后将使用此方法获取值
如果这仍然不起作用(渲染中的空白值),您可以尝试禁用GRMustache安全功能(请参阅)
如果您遇到任何其他问题,请直接在存储库中打开一个问题:
2015年2月2日编辑:GRMustache.swift退出:使用valueForKey应使您能够使用其名称访问属性。确保您正在使用继承NSObject的对象
class people: NSObject {
var age: NSString = "44"
var height: NSString = "153"
}
let person:people = people()
let stringVariable = "age"
person.valueForKey("age")
// Print "44"
person.valueForKey("\(stringVariable)")
// Print "44"
这是一个使用反射的小技巧。可以使用以下内容
protocol PropertyReflectable { }
extension PropertyReflectable {
subscript(key: String) -> Any? {
let m = Mirror(reflecting: self)
for child in m.children {
if child.label == key { return child.value }
}
return nil
}
}
struct Person {
let name: String
let age: Int
}
extension Person : PropertyReflectable {}
然后创建一个人物
,并访问其键控属性
let p = Person(name: "John Doe", age: 18)
p["name"] // gives "John Doe"
p["age"] // gives 18
let p = Person(name: "John Doe", age: 18)
p["name"] // gives "John Doe"
p["age"] // gives 18
您可以修改下标以始终返回属性值的插值字符串。Shim的上述答案在Swift 4中不再有效。有两件事你应该注意 首先,如果要使用
value(forKey:)
函数,则类必须继承NSObject
其次,由于Objective-C对值类型一无所知,您必须将@objc
关键字放在您的值类型属性前面,Swift将为您完成繁重的工作
以下是一个例子:
import Foundation
class Person: NSObject {
@objc var name: String = "John Dow"
@objc var age: Int = 25
@objc var height: Int = 180
subscript(key: String) -> Any? {
return self.value(forKey: key)
}
}
let person: Person = Person()
person["name"] // "John Dow"
person["age"] // 25
person["height"] // 180
在Benzi的答案中添加一些语法糖:
protocol PropertyReflectable { }
extension PropertyReflectable {
subscript(key: String) -> Any? {
let m = Mirror(reflecting: self)
return m.children.first { $0.label == key }?.value
}
}
struct Person {
let name: String
let age: Int
}
extension Person : PropertyReflectable {}
然后创建一个人物
,并访问其键控属性
let p = Person(name: "John Doe", age: 18)
p["name"] // gives "John Doe"
p["age"] // gives 18
let p = Person(name: "John Doe", age: 18)
p["name"] // gives "John Doe"
p["age"] // gives 18
属性不是以字典的形式存储的,所以我猜您不能像您希望的那样访问它们。
myUser.name
有什么问题吗?因为名称和标题不是私有的(因为现在还不可能),所以你不会从中受益。我更新了这个问题,解释了为什么我想要这样的东西。我回答这个问题是因为我认为它教你如何订阅,切换,也许有一点关于反射(或缺少反射)。也就是说,我不建议执行上述任何操作。对于Swift 3.0:person.value(forKey:propertyName)
在获取该值之前如何检查该值是否存在?这非常完美。允许我通过字符串名称访问任何属性这是一个很好的解决方案,但应该注意,这(以及一般的反射)不适用于Swift中的计算属性