0

以下代码引发编译错误:

import UIKit

class Initable {
    required init() {}
}

class NestedObject:Initable {
    var nestedProp:String? = nil
}

class MyObj {
    var name:String? = nil
    var value:Int? = nil
    var otherVals:[String]? = nil
    var nestedObj:NestedObject? = nil
}

let obj = MyObj()
var nestedObj = obj[keyPath: \MyObj.nestedObj]
if(nestedObj == nil) {
    nestedObj = type(of: obj[keyPath: \MyObj.nestedObj]).init()
}
nestedObj![keyPath: \NestedObject.nestedProp] = "NEST ME BABY!!"
obj[keyPath: \MyObj.nestedObj] = nestedObj!

obj

这是因为type(of: obj[keyPath: \MyObj.nestedObj]),NestedObject?当然不能初始化。我需要一种方法来解开可选类型并获得非可选类型NestedObject

必须维持的假设。

  • 我必须使用可选项,因为有可能nestedObj为零。
  • 我不知道是什么类型NestedObject。它可以是任何类型,但我确信这些类型都是Initable.
  • 我需要能够nestedObject通过 keypath 设置我的属性。
  • 如果nestedObject是 nil,我需要创建一个新NestedObject的并通过 keypath 设置值。

这是较大系统的一小部分,因此必须考虑上述假设。我无法改变那些。

4

1 回答 1

1

您可以使用可选Wrapped类型来初始化嵌套对象:

let obj = MyObj()
let nestedObj = type(of: obj[keyPath: \MyObj.nestedObj]).Wrapped()
nestedObj[keyPath: \NestedObject.nestedProp] = "NEST ME BABY!!"

print(nestedObj.nestedProp ?? "")  // "NEST ME BABY!!"

如果您希望生成的对象也是可选的:

let obj = MyObj()
var nestedObj = obj[keyPath: \MyObj.nestedObj]
if nestedObj == nil {
    nestedObj = type(of: obj[keyPath: \MyObj.nestedObj]).Wrapped()
}
nestedObj?[keyPath: \NestedObject.nestedProp] = "NEST ME BABY!!"

您需要添加这些助手:

protocol AnyOptional {
    associatedtype Wrapped
    var optional: Optional<Wrapped> { get }
}

extension Optional: AnyOptional {
    var optional: Optional<Wrapped> { self }
}
于 2021-03-07T16:58:09.763 回答