加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

swift – 将Any转换为Optional

发布时间:2020-12-14 04:46:00 所属栏目:百科 来源:网络整理
导读:我正在处理一组表示实体及其属性的类,然后可以动态地从实体创建编辑器表视图.这些属性使用泛型来捕获属性类型.为了使用KVO并生成自动设置器,这些属性包含键路径.这是属性类的一个非常简化的版本: class XUEntityPropertyEntity: NSManagedObject,Value { le
我正在处理一组表示实体及其属性的类,然后可以动态地从实体创建编辑器表视图.这些属性使用泛型来捕获属性类型.为了使用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")                       */

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读