我正在处理一组表示实体及其属性的类,然后可以动态地从实体创建编辑器表视图.这些属性使用泛型来捕获属性类型.为了使用KVO并生成自动设置器,这些属性包含键路径.这是属性类的一个非常简化的版本:
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< MyEntity,NSDate?>(keyPath:“optionalDate”)
这里的问题是,在setValue方法中,对AnyObject的强制转换将失败,因为值为Optional< NSDate>,它不能转换为AnyObject – objValue为?即使objValue为.some(_),NSDate也将返回nil.
我正在寻找一种解决方案,如何通过检测和解包可选的自动设置器来解决这个问题.
我尝试的任何强制转换都会导致编译器抱怨转换为更可选的类型,或者最终将Optional包含在另一个Optional中.
有谁知道如何检测Any的值是否是可选的,如果是,从可选中提取值,将其转换为AnyObject?
举个例子在操场上试试:
let any: Any = Optional<String>("123") any.dynamicType // -> Optional<String>.Type var object: AnyObject? = nil /// ... -> put value from `any` to `object`.
解决方法
您可以通过添加伪协议并使用is进行类型检查来检查可选类型,并在Mirror(..)之后用于从可选的Any提取实际类型值:
protocol IsOptional {} extension Optional : IsOptional {} /* Detect if any is of type optional */ let any: Any = Optional<String>("123") var object : AnyObject? = nil switch any { case is IsOptional: print("is an optional") if let (_,a) = Mirror(reflecting: any).children.first { object = a as? AnyObject } default: print("is not an optional") } /* Prints "is an optional" */ /* Detect if any2 is of type optional */ let any2: Any = String("123") switch any2 { case is IsOptional: print("is an optional") // ... default: print("is not an optional") } /* Prints "is not an optional" */
Charlie Monroes自己的最终解决方案非常简洁(1!).我想我会添加一个补充.
鉴于已定义协议_XUOptional并且由它扩展了可选类型(如Charlies的答案),您可以使用可选链接和nil合并运算符处理任何可选或不在一行中的事件:
let anyOpt: Any = Optional<String>("123") let anyNotOpt: Any = String("123") var object: AnyObject? object = (anyOpt as? _XUOptional)?.objectValue ?? (anyOpt as? AnyObject) /* anyOpt is Optional(..) and left clause of nil coalescing operator returns the unwrapped .objectValue: "123" as 'AnyObject' */ object = (anyNotOpt as? _XUOptional)?.objectValue ?? (anyNotOpt as? AnyObject) /* anyNotOpt is not optional and left-most optional chaining of left clause returns nil ('anyNotOpt as? _XUOptional' -> nil). In that case,right clause will successfully cast the non-optional 'Any' type to 'AnyObject' (with value "123") */
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。