Many ways of defining a Swift dictionary
There are still more for example:
var dic7 : [String:Int] = [:]
but yes, they are all identical.
Basically, unless the type is not included in the part right from the equation sign, type annotations in declaration lines are not needed because the compiler can infer the type.
How do I put different types in a dictionary in the Swift Language?
You can achieve plist-like nested structures using Any
type for dictionary values which is Swift's somewhat counterpart to Objective-C's id
type but can also hold value types.
var response = Dictionary<String, Any>()
response["user"] = ["Login": "Power Ranger", "Password": "Mighty Morfin'"]
response["status"] = 200
EDIT:
Any
seems to be better than AnyObject
because in the above code response["status"]
is of type Swift.Int
, while using value type of AnyObject
it is __NSCFNumber
.
Swift: declare an empty dictionary
var emptyDictionary = [String: String]()
var populatedDictionary = ["key1": "value1", "key2": "value2"]
Note: if you're planning to change the contents of the dictionary over time then declare it as a variable (var
). You can declare an empty dictionary as a constant (let
) but it would be pointless if you have the intention of changing it because constant values can't be changed after initialization.
How to create and add values to Dictionary in swift
This is a known issue, apparently not fixed yet (see Is it possible to have a dictionary with a mutable array as the value in Swift)
The workaround would be to create a new variable with your array and then assign it back:
var dict = [String: AnyObject]()
dict["GenInfo"] = ["FirstName":"first","LastName":"last","Phone":"phone"]
dict["Language"] = ["langage1", "langage2"]
if var languages = dict["Language"] as? [String] {
languages.append("langage3")
dict["Language"] = languages
}
Making a Dictionary in Swift
I finally found it out how can i do it.
I use a struct with what I want like this:
var userDictionary = [Int : Event]()
struct Event {
var nameEvent: String
var nameMagazi: String
}
And then i use this:
if let objects = objects {
for object in objects {
let post = object["idEvent"] as? PFObject
let post2 = post!["idMagazi"] as? PFObject
let nameEvent = post!["name"] as! String
let idEvent = post?.objectId
let nameMagazi = post2!["name"] as! String
self.events[self.i] = Event(nameEvent: nameEvent , nameMagazi: nameMagazi)
self.i += 1
}
print(self.events[1]!.nameEvent)
}
Thank you all for your answers!
Make a Swift dictionary where the key is Type ?
Unfortunately, it's currently not possible for metatype types to conform to protocols (see this related question on the matter) – so CellThing.Type
does not, and cannot, currently conform to Hashable
. This therefore means that it cannot be used directly as the Key
of a Dictionary
.
However, you can create a wrapper for a metatype, using ObjectIdentifier
in order to provide the Hashable
implementation. For example:
/// Hashable wrapper for a metatype value.
struct HashableType<T> : Hashable {
static func == (lhs: HashableType, rhs: HashableType) -> Bool {
return lhs.base == rhs.base
}
let base: T.Type
init(_ base: T.Type) {
self.base = base
}
func hash(into hasher: inout Hasher) {
hasher.combine(ObjectIdentifier(base))
}
// Pre Swift 4.2:
// var hashValue: Int { return ObjectIdentifier(base).hashValue }
}
You can then also provide a convenience subscript on Dictionary
that takes a metatype and wraps it in a HashableType
for you:
extension Dictionary {
subscript<T>(key: T.Type) -> Value? where Key == HashableType<T> {
get { return self[HashableType(key)] }
set { self[HashableType(key)] = newValue }
}
}
which could then use like so:
class CellThing {}
class A : CellThing {}
class B : CellThing {}
var recycle: [HashableType<CellThing>: [CellThing]] = [:]
recycle[A.self] = [A(), A(), A()]
recycle[B.self] = [B(), B()]
print(recycle[A.self]!) // [A, A, A]
print(recycle[B.self]!) // [B, B]
This should also work fine for generics, you would simply subscript your dictionary with T.self
instead.
Unfortunately one disadvantage of using a subscript with a get
and set
here is that you'll incur a performance hit when working with dictionary values that are copy-on-write types such as Array
(such as in your example). I talk about this issue more in this Q&A.
A simple operation like:
recycle[A.self]?.append(A())
will trigger an O(N) copy of the array stored within the dictionary.
This is a problem that is aimed to be solved with generalised accessors, which have been implemented as an unofficial language feature in Swift 5. If you are comfortable using an unofficial language feature that could break in a future version (not really recommended for production code), then you could implement the subscript as:
extension Dictionary {
subscript<T>(key: T.Type) -> Value? where Key == HashableType<T> {
get { return self[HashableType(key)] }
_modify {
yield &self[HashableType(key)]
}
}
}
which solves the performance problem, allowing an array value to be mutated in-place within the dictionary.
Otherwise, a simple alternative is to not define a custom subscript, and instead just add a convenience computed property on your type to let you use it as a key:
class CellThing {
// Convenience static computed property to get the wrapped metatype value.
static var hashable: HashableType<CellThing> { return HashableType(self) }
}
class A : CellThing {}
class B : CellThing {}
var recycle: [HashableType<CellThing>: [CellThing]] = [:]
recycle[A.hashable] = [A(), A(), A()]
recycle[B.hashable] = [B(), B()]
print(recycle[A.hashable]!) // [A, A, A]
print(recycle[B.hashable]!) // [B, B]
Multiple values for one Key in Swift Dictionary
You're getting a bad error message. The real issue is that [Bool, String]
isn't a valid type. There is no way to specify an array of fixed length with specific types in specific spots. Instead, use a tuple:
var cat1 = [String: (Bool, String)]()
var cat2: [String: (Bool, String)] = ["Bob": (false, "Red"), "Albert": (true, "Black")]
Swift Dictionary With Expansive Type Constraints
If you want to a Dictionary
where the value can be a String
, an Int
, a Bool
or a MyClass
you should
Define your protocol
protocol MyDictionaryValue { }
Conform String, Int, Bool and MyClass to MyDictionaryValue
extension String: MyDictionaryValue { }
extension Int: MyDictionaryValue { }
extension Bool: MyDictionaryValue { }
extension MyClass: MyDictionaryValue { }
Declare your dictionary
var dict = [String:MyDictionaryValue]()
Usage
dict["a"] = "a string"
dict["b"] = 1
dict["c"] = true
dict["d"] = MyClass()
dict["e"] = CGPointZero // error
dict["f"] = UIView() // error
Related Topics
Fatal Error: Array Index Out of Range in Swift Xcode6
How to Set Font Size of Sklabelnode to Fit in Fixed Size (Swift)
Continuously Train Coreml Model After Shipping
How to Link to a 3Rd Party Swift Framework
Nsmanagedobject Changes Do Not Trigger Objectwillchange
Read and Write Permission for User Selected Folder in MAC Os App
Slide Sidebar Menu iOS 8 Swift
Codable Class Does Not Conform to Protocol Decodable
Appearance Proxies/Ui_Appearance_Selector in Swift
Add a Border with Cornerradius to an Image in Swiftui Xcode Beta 5
How to Destroy a Singleton in Swift
How to Reset Intent Extension Configurations in Widgetkit
How to Compare Just the Time of a Date in Swift
Scenedidload Being Called Twice
Building a Spritekit/Gamekit Leaderboard Within a Specific Scene
How to Create an Array with Incremented Values in Swift
Wrapping a Generic Method in a Class Extension
How to Distinguish Between Multiple Uipickerviews on One Page