What is the difference between Dictionary<String, Any?> and [String:Any?] - swift

I want to pass an optional dictionary parameter in Swift function, I tried declaring the function as
func myFunction(_ type:Int, params:Dictionary<String,Any?>?)
and also
func myFunc(_ type:Int, params:[String:Any?]?)
I get warning "Expression implicitly coerced from Any? to Any" with first declaration when I try to pass a dictionary but not with second. I need to know what is the difference between the two and why the warning. FYI, here is how I pass the dictionary in both cases:
myFunc(1, params:["key1": value1, "key2": value2])

According to Swift documentation, they are identical:
The type of a Swift dictionary is written in full as Dictionary<Key,
Value>, where Key is the type of value that can be used as a
dictionary key, and Value is the type of value that the dictionary
stores for those keys.
You can also write the type of a dictionary in shorthand form as [Key:
Value]. Although the two forms are functionally identical, the
shorthand form is preferred and is used throughout this guide when
referring to the type of a dictionary.
I'm using Xcode Version 8.0 and i couldn't regenerate your issue.

They are just different syntactic sugar for dictionary declaration and one type will not work in all cases which are kind of a bug.
For Example,
var msSet = [Vertex<Int> : Double]()
I have asked a question related to it.
Swift Dictionary Initialization of custom type gives: '>' is not a postfix unary operator error

Related

Casting to a type held in a variable

I am attempting to cast a variable to a different type that is held in a variable or is the return type of a function. Here is the idea:
let i = 1 as type(of: 3.14)
But when I do this, I get a couple of errors:
Use of undeclared type 'type'
Consecutive statements on a line must be separated by ';' (This inserts a semi-colon between type and (of: 3.14))
And a warning:
Expression of type (of: Double) is unused
How to I cast a value to a type that is held in a variable?
Swift (currently) requires the Type assignment at compile time. You can do some things like this, but you will need to write a converter for each type combination you want to use, e.g:
func convertType(from item: Int) -> Float {
return Float(item)
}
var item: Float = convertType(from: 1)
I would caution going down this road and try and get used to Swift's way of doing things. If you absolutely need it you should be able to use some generic functions with a protocol like FloatConvertable to handle this more simply.
The Swift grammar doesn't allow for these types of expressions. The expression after as must be the name of a type, ie. 1 as Double (though, as vadian points out, you can't cast numeric types to each other, so a better example would be mySubClassObject as MySuperClass). Swift is a strongly typed language, which means it needs to know the types of all variables at compile time.

Why aren't Swift Strings bridged to NSString in a Dictionary when Foundation is imported? [duplicate]

A fairly simple piece of code
var dict: [String: AnyObject] = [:]
dict["key"] = "value"
generates the following compile-time error
Cannot assign value of type 'String' to type 'AnyObject?'
Simple type checks tell me that String is AnyObject
"value" is AnyObject // returns true
I could change AnyObject to Any and everything would work
var dict: [String: Any] = [:]
dict["key"] = "value"
but I want to understand why do I get the error? Is String no longer AnyObject? Or is this a bug?
In b6, String no longer magically bridges to NSString. String is not a class; it's a struct. You need to do the bridging by hand:
dict["key"] = "value" as AnyObject
The fact that is still seems to be bridging is likely a bug and should be reported.
It goes without saying that [String: AnyObject] and [String: Any] should be used as little as possible in your code.
(Make sure to follow the link Hamish provides in the comments below.)
I'll complement to #RobNapier's answer with some official sources.
The removal of the implicit bridging mechanisms was accepted in the following Swift evolution proposal, to be implemented for Swift 3
SE-0072: Fully eliminate implicit bridging conversions from Swift
Previously, implicit conversions were available from some Swift native types to associated Objective-C types (Swift types conforming to private protocol _ObjectiveCBridgeable, e.g. natively Int, String, )
For this reason, we decided to make a compromise. We would require
explicit bridging casts when converting from a bridged Objective-C
type to its associated Swift value type (E.g., NSString -> String),
but not the other way around.
... [From SE-0072]
With Swift 3, such implicit conversion mechanisms will no longer be available.
With the introduction of Objective-C generics last year, along with
all of the awesome improvements to API importing happening for Swift
3, I think it’s time that we take another look at completing this
work.
...
I propose that we fully eliminate implicit bridging conversions in
Swift 3. This would mean that some users might have to introduce
more explicit casts in their code, but we would remove another special
case from Swift's type system and be able to further simplify the
compiler.
...
Code that previously relied on implicit conversions between Swift
value types and their associated bridged Objective-C type will now
require a manual coercion via an as cast.
Finally, the release notes for Xcode 8 beta 6 (login required) states that this proposal has now been implemented for beta 6:
New in Xcode 8 beta 6 - Swift Compiler: Swift Language
...
Bridging conversions are no longer implicit. The conversion from a Swift value type to its corresponding object can be forced with as.
For example: string as NSString. Any Swift value can also be
converted to its boxed id representation with as AnyObject.
(SE-0072)
W.r.t. new "boxed id" allowing explicit conversion for any Swift value to AnyObject, see e.g. the following thread:
AnyObject not working in Xcode8 beta6?

Creating a new dictionary in Swift - when to use which method.

I see it is possible to create dictionaries in swift as follows
var dict1 = [String: Int]()
var dict2 = Dictionary<String, Int>()
and then use it as normal. When should I use which method of creating dictionaries?
The Apple produced book "The Swift Programming Language" says
The type of a Swift dictionary is written in full as Dictionary<Key, Value>, where Key is the type of value that can be used as a dictionary key, and Value is the type of value that the dictionary stores for those keys.
You can also write the type of a dictionary in shorthand form as [Key: Value]. Although the two forms are functionally identical, the shorthand form is preferred and is used throughout this guide when referring to the type of a dictionary.
so it seems that the shorthand form is preferred. Probably because it looks a bit cleaner.

Swift: equatable dictionary cannot be passed to a generic function

I really need to pass any equatable structs/types/objects to this setEquatable function.
Any idea how can I solve this problem?
public func ==(l: [String: String], r: [String: String]) -> Bool {
return true // just a stub
}
func setEquatable<T: Equatable>(v: T) {
//...
}
let isEqual = ["1": "2"] == ["1": "2"]
setEquatable(v: ["1": "2"])
For people who vote for closing the question due to duplication: I would not close the question as duplication because that way you will not prevent the same question being asked again in future. People who have problems with their code and want to understand the gist will find this question very useful. They most probably would not know anything about conditional conformance, but they have their code that doesn't compile.
This is currently a limitation of Swift's type system that is well-known and on the roadmap to fix. The specific feature being discussed to fix this is "conditional conformance" to protocols for generic types. In essence, the Dictionary type can't be universally declared Equatable, because you don't know up front how to compare every possible type of value it may hold (some of which might not themselves be Equatable).
Conditional conformance would allow you to create an extension that says that Dictionary sometimes conforms to Equatable, specifically under the condition when its Value type is Equatable. And in that case, Dictionary equality can be defined as a function that compares the equality of all keys and all values in both Dictionary instances being checked.
Here is a summary of this feature and others under consideration:
https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#conditional-conformances-
Until this type system upgrade is implemented though, there is unfortunately no way to treat any Dictionary as Equatable directly. You can however create Equatable-conforming wrapper types around Dictionaries, or overload your setEquatable function to also accept Dictionaries with Equatable values and handle accordingly.

as! vs as operator in Xcode 6.3 in Swift

Swift changed a lot with Xcode 6.3. I had to replace dozens of places in each of my app as -> as!. Why, what are the rules now?
Prior to Swift 1.2, the as operator could be used to carry out two different kinds of conversion, depending on the type of expression being converted and the type it was being converted to:
Guaranteed conversion of a value of one type to another, whose success can be verified by the Swift compiler. For example, upcasting (i.e., converting from a class to one of its superclasses) or specifying the type of a literal expression, (e.g., 1 as Float).
Forced conversion of one value to another, whose safety cannot be guaranteed by the Swift compiler and which may cause a runtime trap. For example downcasting, converting from a class to one of its subclasses.
Swift 1.2 separates the notions of guaranteed conversion and forced conversion into two distinct operators. Guaranteed conversion is still performed with the as operator, but forced conversion now uses the as! operator. The ! is meant to indicate that the conversion may fail. This way, you know at a glance which conversions may cause the program to crash.
Source: https://developer.apple.com/swift/blog/?id=23
The practical difference is this:
var optionalString = dict.objectForKey("SomeKey") as? String
optionalString will be a variable of type String?. If the underlying type is something other than a String this will harmlessly just assign nil to the optional.
var optionalString = dict.objectForKey("SomeKey") as! String?
This says, I know this thing is a String?. This too will result in optionalString being of type String?, but it will crash if the underlying type is something else.
The first style is then used with if let to safely unwrap the optional:
if let string = dict.objectForKey("SomeKey") as? String {
// If I get here, I know that "SomeKey" is a valid key in the dictionary, I correctly
// identified the type as String, and the value is now unwrapped and ready to use. In
// this case "string" has the type "String".
println(string)
}
According to the release notes:
The notions of guaranteed conversion and “forced failable” conversion
are now separated into two operators. Forced failable conversion now
uses the as! operator. The ! makes it clear to readers of code that
the cast may fail and produce a runtime error. The “as” operator
remains for upcasts (e.g. “someDerivedValue as Base”) and type
annotations (“0 as Int8”) which are guaranteed to never fail.