我正在开发一组代表实体及其属性的类,可以从这些实体动态生成编辑表视图。这些属性使用泛型来捕获属性类型。为了使用KVO并生成自动setter,这些属性包含一个键路径。下面是一个非常简化的属性类示例:
class XUEntityProperty<Entity: NSManagedObject, Value> {
let keyPath: String
var customSetter: ((Entity, Value) -> Void)?
func setValue(value: Value, onEntity entity: Entity) {
/// If custom setter is set, use it.
if let setter = self.customSetter {
setter(entity, value)
return
}
/// Otherwise set the object using the keypath.
guard let objValue = value as? AnyObject else {
XUThrowAbstractException() // Use custom setter
}
entity.setValue(objValue, forKeyPath: self.keyPath)
}
}
这个方法几乎可以适用于任何内容,但是可选项却有问题。例如: let property = XUEntityProperty(keyPath: "optionalDate")
问题在于,在setValue方法中,将Optional转换为AnyObject会失败,因为value是Optional类型,不能强制转换为AnyObject - objValue as? NSDate即使objValue是.Some(_)也会返回nil。
我正在寻找一种解决方案,通过检测和取消包装Optional,在自动设置器中解决此问题。
我尝试的任何类型转换都会导致编译器抱怨要么将其强制转换为更多的Optional类型,要么最终将Optional包装到另一个Optional中。
是否有人知道如何检测Any值是否是Optional,并从Optional中提取值并将其转换为AnyObject?
以下是在playground中尝试的示例:
let any: Any = Optional<String>("123")
any.dynamicType // -> Optional<String>.Type
var object: AnyObject? = nil
/// ... -> put value from `any` to `object`.
Mirror
;效果很好。 - dfribany
实际上是一个可选项:如果您使用let any: Any = String(“123”)
进行测试,则以上解决方案将由于强制转换(as!
)为_XUOptional
而产生运行时异常。我个人更喜欢Mirror
解决方案,因为您不需要扩展基本的Optional
类型,而可以仅使用“外部”方法来工作。 - dfribif let optional = obj as? _XUOptional { return optional.objectValue }
。甚至更短 -(obj as? _XUOptional)?.optionValue
。 - Charlie Monroeobject = (any as? _XUOptional)?.objectValue
很好地工作了,干得好! :) - dfrib