Подтвердить что ты не робот

Как поместить различные слова в словарь на языке Swift?

Swift позволяет только словарь содержать один тип.

Здесь определение, взятое из книги Свифта:

Словарь - это контейнер, в котором хранятся несколько значений одного и того же типа

[...]

Они отличаются от классов Objective-C s NSDictionary и NSMutableDictionary, которые могут использовать любой тип объекта в качестве своих ключей и значений и не предоставляют никакой информации о природе этих объектов.

Если это так, то как мы будем создавать вложенные словари?

Предположим, что у нас есть plist, в котором содержатся элементы String, Array и Dictionary. Если Im разрешено удерживать только один и тот же тип элементов (строка, массив и т.д.), То как я буду использовать разные типы элементов, хранящихся в plist?

Как поместить различные типы в один и тот же словарь в Swift?

4b9b3361

Ответ 1

Вы можете достичь вложенных структур в виде plist, используя тип Any для значений словаря, который является Swift несколько аналогичным типу Objective-C id, но также может содержать типы значений.

var response = Dictionary<String, Any>()
response["user"] = ["Login": "Power Ranger", "Password": "Mighty Morfin'"]
response["status"] = 200

EDIT:

Any кажется лучше, чем AnyObject, потому что в приведенном выше коде response["status"] имеет тип Swift.Int, при использовании типа значения AnyObject это __NSCFNumber.

Ответ 2

Как было предложено, вы можете использовать тип Any для представления значений словаря plist. Но тогда как вы работаете с данными? Бросать любое значение в любое время, когда вы просматриваете его из словаря? Это действительно грязно. Лучшим, более безопасным по типу способом моделирования plist было бы использовать списки Swift, также известные как алгебраические типы данных или дискриминационные союзы. Они позволяют вам точно указать, какие типы разрешены в словаре, и избегать приведения в действие. Здесь реализована реализация:

// An atomic (i.e. non-collection) data type in a plist.
enum PListNode {
  case PLN_String(String)
  case PLN_Integer(Int)
  case PLN_Float(Double)
  case PLN_Bool(Bool)
  case PLN_Date(CFDate)
  case PLN_Data(CFData)
}

На самом атомном уровне в plist могут храниться только вышеуказанные типы данных. Каждый "node" в plist может в конечном счете быть только одним из этих типов. Итак, мы создаем перечисление, которое позволяет нам указать это.

// A value that can be stored in a plist Dictionary key-value pair.
enum PListValue {
  case PLV_Node(PListNode)
  case PLV_Array(PListNode[])
  case PLV_Dictionary(Dictionary<String, Box<PListValue>>)
}

typealias PList = Dictionary<String, Box<PListValue>>

Пластик - это, в основном, словарь пар ключ-значение, и каждое значение может быть либо атомным (то есть не-коллекционным) значением; или это может быть массив атомных значений; или это может быть словарь пар значений значения plist. Вышеописанное перечисление выражает эти ограничения, а типалиас дает тип plist легко запоминающееся имя.

Учитывая вышеуказанные типы, мы можем полностью выразить любой данный plist безопасным типом, например:

// Example translated from
// https://developer.apple.com/library/Mac/documentation/Darwin/Reference/ManPages/man5/plist.5.html
let myPlist: PList = [
  "Year Of Birth": Box(PLV_Node(PLN_Integer(1965)))
, "Pets Names":    Box(PLV_Array([]))
, "Picture":       Box(PLV_Node(PLN_Data(...)))
, "City of Birth": Box(PLV_Node(PLN_String("Springfield")))
, "Name":          Box(PLV_Node(PLN_String("John Doe")))
, "Kids Names":    Box(
    PLV_Array([PLN_String("John"), PLN_String("Kyra")])
  )
]

Что значит быть безопасным здесь, так это то, что вы можете обрабатывать любой данный plist с помощью инструкции switch и охватывать все возможности без необходимости кастинга. Вы устраняете целый класс потенциальных ошибок времени выполнения. Например:.

// See https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Enumerations.html#//apple_ref/doc/uid/TP40014097-CH12-XID_189 for explanation
switch myPlist["Year Of Birth"] {
  case Box(.PLV_Node(let plvNodeValue)):
    ...
  case Box(.PLV_Array(let plvArrayValue)):
    ...
  case Box(.PLV_Dictionary(let plvDictionaryValue)):
    ...
}

Обратите внимание, что необходимо обернуть рекурсивные структуры данных в "поле" (указатель на фактическое значение), чтобы их размеры были конечными.

Ответ 3

Использование: Словарь < String, AnyObject >

var dict: Dictionary<String, AnyObject> = [
    "number": 1,
    "string": "Hello",
]

Ответ 4

NSObject работает для моего случая, а "Any" не

var d:Dictionary<String,NSObject> = [:]
d["key1"] = "ddd"
d["key2"] = 111  //OK
NSLog("%@", d) //OK

var d2:Dictionary = Dictionary<String,Any>()
d2["key1"] = "ddd"
d2["key2"] = 111
NSLog("%@", d2) //I got error here

Ответ 5

Используйте NSMutableDictionary следующим образом:

var dictInfo : NSMutableDictionary = [ "lang_key": "1"]
    dictInfo["food_type"]     =   lbl_TypeOfFood.text
    dictInfo["search_text"]   =   txt_Search.text
    dictInfo["date"]          =   lbl_Date.text
    dictInfo["opening_hours"] =   lbl_OpeningHours.text

надеюсь, что это сработает нормально.

Ответ 6

NSMutableDictionary to Dictionary работает как шарм и позволит вам поместить различные типы в словарь на языке Swift:

let nsMutableDictionary = NSMutableDictionary()
nsMutableDictionary[NSFontAttributeName] = UIFont(name: "HelveticaNeue", size: 12.0)!
nsMutableDictionary[NSForegroundColorAttributeName] = UIColor.redColor()

let dictionary: Dictionary<NSObject, AnyObject> = nsMutableDictionary

self.attributedPlaceholder = NSAttributedString(string: textParam, attributes: dictionary)

Ответ 7

let dictionary : Dictionary = [
    "key": "value",
    "key2": 2,
    "key3": NSString(),
    2: "test",
]

Можно указать типы, которые ограничивают словарь

let dictionary : Dictionary<String, String> = [
    "key": "value",
    "key2": 2, // This errors
]