【发布时间】:2015-10-13 21:06:13
【问题描述】:
在 Swift 中不能使用 .setValue(..., forKey: ...)
- 像
Int这样的可空类型字段? - 类型为
enum的属性 - 一个可以为空的对象数组,例如
[MyObject?]
有一种解决方法,那就是覆盖对象本身的 setValue forUndefinedKey 方法。
因为我正在编写基于反射的通用对象映射器。见EVReflection我想尽量减少这种手动映射。
还有其他方法可以自动设置这些属性吗?
可以在我的库here 的单元测试中找到解决方法 这是代码:
class WorkaroundsTests: XCTestCase {
func testWorkarounds() {
let json:String = "{\"nullableType\": 1,\"status\": 0, \"list\": [ {\"nullableType\": 2}, {\"nullableType\": 3}] }"
let status = Testobject(json: json)
XCTAssertTrue(status.nullableType == 1, "the nullableType should be 1")
XCTAssertTrue(status.status == .NotOK, "the status should be NotOK")
XCTAssertTrue(status.list.count == 2, "the list should have 2 items")
if status.list.count == 2 {
XCTAssertTrue(status.list[0]?.nullableType == 2, "the first item in the list should have nullableType 2")
XCTAssertTrue(status.list[1]?.nullableType == 3, "the second item in the list should have nullableType 3")
}
}
}
class Testobject: EVObject {
enum StatusType: Int {
case NotOK = 0
case OK
}
var nullableType: Int?
var status: StatusType = .OK
var list: [Testobject?] = []
override func setValue(value: AnyObject!, forUndefinedKey key: String) {
switch key {
case "nullableType":
nullableType = value as? Int
case "status":
if let rawValue = value as? Int {
status = StatusType(rawValue: rawValue)!
}
case "list":
if let list = value as? NSArray {
self.list = []
for item in list {
self.list.append(item as? Testobject)
}
}
default:
NSLog("---> setValue for key '\(key)' should be handled.")
}
}
}
【问题讨论】:
-
我可以建议您等到 Apple 在秋季发布 Swift 的源代码,因为他们知道如何遍历 Swift 属性。 (反射函数不仅返回 MirrorType 对象的副本,而且还引用每个属性),所以如果 MirrorType 将使其成为开源代码部分,那么您就可以看到它们如何实现这一点并将该方法移植到您的库中。
-
好吧,我可以得到这些值。现在我想设置值
-
没有镜像类型你能得到它们吗?
-
您确实需要使用 reflect(..) 获取 MirrorType 参见底部的 valueForAny 方法:github.com/evermeer/EVReflection/blob/master/EVReflection/pod/…
-
这就是我所说的。你只能通过
reflect函数和MirrorType来获取值,但你不知道Apple在后台是如何做到的。他们可以在运行时以某种方式迭代属性,在他们发布源代码之前我们不知道如何。
标签: swift reflection setvalue