2016-12-20 2 views
4

Я использую KVC для создания унифицированного интерфейса для нужд приложения. Например, одна из моих функций получает объект, который подвергается нескольким проверкам, основанным исключительно на словаре строковых ключей.Как проверить, является ли объект коллекцией? (Swift)

Таким образом, мне нужен способ проверить, является ли объект ключом типа коллекции.

Я ожидал, что смогли сделать некоторые проверки протоколов (например, IEnumerable в C#, чтобы проверить, если это можно перечислить), но это не сработало:

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

Я попытался AnyCollection тоже.

Я знаю, что я мог бы перебирать все основные типы коллекций, просто введя:

if let a = b as? Set { ...} // (or: if a is Set {...}) 
if let a = b as? Array { ...} 
if let a = b as? Dictionary { ...} 

Но это, кажется, не собственно от наследования/полиморфизма точки зрения.

+0

Вы попробовали это http://stackoverflow.com/questions/39536742/in-swift-how-do-i-check-if-an-object-is-a-collection-of-any-type –

+0

Возможно дубликат [Использование isKindOfClass с Swift] (http://stackoverflow.com/questions/24019707/using-iskindofclass-with-swift) –

+0

Я использовал поиск перед публикацией. Начиная с isKindOfClass, он подразумевает итерацию по жестко кодированным типам. Я бы хотел, чтобы надлежащая проверка протокола или что-то в этом роде. – Hexfire

ответ

0

Collection больше не может использоваться для проверки типов, поэтому решение Ahmad F больше не будет компилироваться.

Я проверил. Некоторые люди советуют переходить к коллекциям obj-c и использовать isKindOfClass, другие пытаются использовать отражение (используя Mirror). Ни один из них не является удовлетворительным.

Там довольно прямо вперед, немного грубый, но эффективный способ для выполнения этой задачи с помощью расщепления типа объекта, если мы интересуемся Array, Dictionary или 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 
} 

Использование:

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 

Жесткий код - это недостаток, но он выполняет эту работу.

3

Попробуйте использовать эту функцию:

func isCollection<T>(object: T) -> Bool { 
    switch object { 
    case _ as Collection: 
     return true 
    default: 
     return false 
    } 
} 

Призвание:

// COLLECTION TESTING // 

let arrayOfInts = [1, 2, 3, 4, 5] 
isCollection(object: arrayOfInts) // true 

let setOfStrings:Set<String> = ["a", "b", "c"] 
isCollection(object: setOfStrings) // true 

// [String : String] 
let dictionaryOfStrings = ["1": "one", "2": "two", "3": "three"] 
isCollection(object: dictionaryOfStrings) // true 


// NON-COLLECTION TESTING // 

let int = 101 
isCollection(object: int) // false 

let string = "string" // false 

let date = Date() 
isCollection(object: date) // false 

Надеется, что это помогло.