The following code throws a compile error:
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
This is due to the fact that type(of: obj[keyPath: \MyObj.nestedObj])
is NestedObject?
, which of course cannot be initialized. I need a way to unwrap the optional typing and get the non-optional typing NestedObject
.
Assumptions that have to be maintained.
nestedObj
to be nil.NestedObject
is. It could be any type, but I am assured those types are all Initable
.nestedObject
via a keypath.nestedObject
is nil, I need to create a new NestedObject
and set the value via a keypath.This is a small part of a larger system, so the above assumptions must be considered. I cannot change those.
You can use your optional Wrapped
type to initialize your nested object:
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!!"
If you want the resulting object to be optional as well:
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!!"
You need to add those helpers:
protocol AnyOptional {
associatedtype Wrapped
var optional: Optional<Wrapped> { get }
}
extension Optional: AnyOptional {
var optional: Optional<Wrapped> { self }
}