如何检查对象是否为集合?(迅速)

Hex*_*ire 5 generics collections swift

我广泛使用KVC构建满足应用程序需求的统一界面。例如,我的一个函数获取了一个对象,该对象仅基于字符串键字典进行几次检查。

因此,我需要一种方法来检查键对象是否为集合类型。

我希望能够进行一些协议检查(例如C#中的IEnumerable来检查它是否可以枚举),但是没有成功:

if let refCollection = kvcEntity.value(forKey: refListLocalKey) as? AnySequence<CKEntity> { ... }
Run Code Online (Sandbox Code Playgroud)

我也尝试过AnyCollection。

我知道我可以通过键入以下内容来迭代所有主要集合类型:

if let a = b as? Set { ...} // (or: if a is Set {...})
if let a = b as? Array { ...}
if let a = b as? Dictionary { ...}
Run Code Online (Sandbox Code Playgroud)

但这从继承/多态性的角度来看似乎不合适。

Hex*_*ire 5

Collection 不能再用于类型检查,因此 Ahmad F 的解决方案将不再编译。

我做了一些调查。有些人建议桥接 obj-c 集合并使用isKindOfClass,其他人尝试使用反射(通过使用Mirror)。两者都不令人满意。

如果我们关心的是ArrayDictionary或者Set(列表可以更新),有一种非常直接、有点粗糙但有效的方法来通过拆分对象类型来完成任务:

func isCollection<T>(_ object: T) -> Bool {
    let collectionsTypes = ["Set", "Array", "Dictionary"]
    let typeString = String(describing: type(of: object))

    for type in collectionsTypes {
        if typeString.contains(type) { return true }
    }
    return false
}
Run Code Online (Sandbox Code Playgroud)

用法:

var set : Set! = Set<String>()
var dictionary : [String:String]! = ["key" : "value"]
var array = ["a", "b"]
var int = 3
isCollection(int) // false
isCollection(set) // true
isCollection(array) // true
isCollection(dictionary) // true
Run Code Online (Sandbox Code Playgroud)

硬编码是缺点,但它可以完成工作。