Difference between [String] and Array<String> - arrays

Which is better way to declare Array and Dictionary, I have used both:
Array<String>
[String]
For me [String] is very fast in terms of coding but in reality how both are different in terms of compiler and performance and which one we should follow?

From iOS Developer Library on Swift...
The type of a Swift array is written in full as Array< Element >, where
Element is the type of values the array is allowed to store. You can
also write the type of an array in shorthand form as [Element].
Although the two forms are functionally identical, the shorthand form
is preferred and is used throughout this guide when referring to the
type of an array.
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html

The two are equivalent.
From Apple
Array Type Shorthand Syntax
The type of a Swift array is written in full as Array, where Element is the type of values the array is allowed to store. You can also write the type of an array in shorthand form as [Element]. Although the two forms are functionally identical, the shorthand form is preferred and is used throughout this guide when referring to the type of an array.

I would note one difference is that if you are trying to instantiate an array of objects where you need to specify the module (because of naming collisions) the shorthand form appears to choke.
let array1 = [MyModule.MyClass]() // Compile error: Invalid use of '()' to call a value of non-function type '[MyClass.Type]'
let array2 = Array<MyModule.MyClass>() // Works as expected.
Other situations like optional unwrapping or as parameter typing work using shorthand notation. I only have tried in Swift 2.3

Related

Kotlin array types and class literals

I am trying to deserialize an array of JSON objects with GSON. So the simple call:
val arrayOfFoo = gson.fromJson(source, Array<Foo<*>>::class.java>)
should do the trick. But type erasure tells us, that Foo<*> does not exist at runtime, so the error "Only class literals are allowed on the left hand side of a class literal" pops up. Well, so the solution must be:
val arrayOfFoo = gson.fromJson<Array<Foo<*>>>(source, Array::class.java)
Unfortunatelly, now the Kotlin compiler magic - that turns arrays of Wrapper types into primitive arrays - can not be sure what to do and tells us:
"Array class literals require a class type. Please specify one in angle brackets".
But, wait: This is, what did not work a second ago. Using
Array<Foo>::class.java
does not work, too, since now the compiler tells us: "One type argument is expected for Foo".
I personally can not see a way to solve that. Is it impossible to give a class literal of a typed array, which's type also expects a type parameter?
You can get the array class from an array instance, for example either one of
arrayOf<Foo<*>>()::class.java
java.lang.reflect.Array.newInstance(Foo::class.java, 0)::class.java
The basic problem: You need to specify the type of your array. This is done using a TypeToken in Gson.
I hope this helps:
val listType = object : TypeToken<Array<String>>() {}.type
val json = """["1"]"""
val yourClassList :Array<String> = Gson().fromJson(json, listType)
print(yourClassList)
Note that for primitives, it is simpler: Gson().fromJson(json, IntArray::class.java)

Creating arrays

I'm about to learn Swift 2 and got to the chapter about arrays. There I found out that both of the following do (at least what I can see) the same:
First one:
var shoppinglist = [String](arrayLiteral: "Eggs", "Milk");
Second one:
var shoppinglist2: [String] = ["Eggs", "Milk"];
What exactly is the difference between those two or is there no difference at all? Which one should I prefer?
There is no functional difference but you should prefer the second expression.
The syntax [String] is just a shorthand for Array<String>, which says that you are describing the generic Array type specialized to hold String values.
However, it's more common and readable to use that shorthand syntax just to describe a type, not to actually invoke the initializer, as you are doing in the first example. Also, there's no need to call the initializer that takes the arrayLiteral parameter. The point of that parameter is to allow you to initialize an array with a literal, as you are doing in the second example.
Your second example is good.
Another option is simply
var shoppinglist3 = ["Eggs", "Milk"]
which relies on type inference.
And you don't need the semicolons
Its just syntactic sugar to make your code less verbose, you should in general prefer less verbose code unless it is for some reason unclear. Also you can drop the type annotation since it is redundant as the type can be inferred from the expression.
So ideally:
var shoppinglist = ["Eggs", "Milk"]
The second one is more common, in this case you can also exclude : [String] because it's inferred from the right hand side value. They have different syntax but evaluate to the same thing. The first one is commonly used when creating either empty arrays or repeated arrays like this:
var empties = [Float]()
var doubles = [Double](count: 15, repeatedValue: 1.0)

Differences in array declaration in Swift

What's the difference between var list = NSMutableArray() and var list:NSMutableArray = [] when declaring in Swift?
As far as I know there is no effective difference.
With the first statement you are using the type inference feature of Swift. You create an instance of a class and from the assignment of that instance to a var the compiler infers the type.
In the second statement you explicitly define the type of list. The assignment on the right side of the equal sign now instantiates an empty Swift Array but due to the explicit type of NSMutableArray it will be casted to this class.
The right expression of the equal sign does the same as NSMutableArray()does, but by using [] you have a smart shorthand option to instantiate the NSMutableArray with values like this [2,1,4] or [someObject, someOtherObject]etc.
Thanks to #Neo.
In the second statement the compiler would not complain about leaving the instantiation on the right side, it just would be nil implicitly. On the other hand the first statement without the NSMutableArray() expression would not be possible.
Keep in mind that NSMutableArrayis a class from the Foundation framework and was primarily used in Objective-C context, whereas Swift offers an own collection type for this kind of lists. They are not the same, but implicitly casted by the compiler.
Hope this makes things clear.
Just like JulianM said, there is no difference... Both are declaring / instantiating an NSMutableArray :-)
The only "difference" that there is
var list = NSMutableArray()
This line of code declares list and inherits his type of the instantiated NSMutableArray...
var list:NSMutableArray = []
While this line of code declares list AS NSMutableArray and instantiates it as an NSMutableArray...
But thats just a writing difference... Both mean the same...

Can an array be initialised with literals of different types in Swift?

As per the Swift document, if the type of an array is inferred from the array literals. Now I am getting confused that if you assign an Int,String and Double values for an array there are no errors being thrown.
Try the same code here on an online Swift compile` or an Xcode with version 6.3.1 or 6.3.2. I have tried the above one on 6.4.
Now can anyone please tell me what will be the type of array?
And how come this array is allowing to initialise it with different data types?
Thank you.
Yes, you can make an array of Any:
var sample1: [Any] = [12,"Hello"]
This is almost always a mistake, though, which is why Swift requires you to explicitly show the type. The vast majority of things you would want to do (except parse JSON in Swift...) can be done without resorting to this kind of data structure.
For some kinds of arrays, you can use AnyObject rather than Any. This will require all of the elements to be "object-like" which is a little more specific than Any, and is more interoperable with ObjC:
var sample1: [AnyObject] = [12,"Hello"]
This is also almost always a mistake.
The error you're seeing is that Swift needs "more context." Since your objects do not share an obvious parent below AnyObject, Swift doesn't know if you really mean that, or if you made a mistake. In most cases, what you want here is an array of some protocol that all of the elements conform to instead.
It is possible but you should try to have your arrays of one data type. It minimizes possibilities for making errors.
So that is why you want to explicitly specify the type of the array to contain Any type of objects.
Your example becomes:
var array: [AnyObject] = [20, 4.0, ""]
Notice that I'm using AnyObject not just Any. The difference between the two is that AnyObject must be a class whereas Any can be just about anything (tuple, struct, ...).
When you make an array of equal types of objects such as:
var array = [20, 4, 8]
The compiler will be kind enough to infer the type for you. So the line above is semantically equal to:
var array: [Int] = [20, 4, 8]
If you need any additional info feel free to ask.

Handling sparse arrays in swift

I'm trying to create a sparse array in Swift. I'm not sure if the problem is in my declaration (no syntax errors detected) or possibly a bug in beta 2?
I am trying to declare an array of 24 class instances as optionals. I then can fill in slots of the array as necessary. Here is the declaration:
var usage = WaterUsage?[](count:24, repeatedValue:nil)
This gets through the Xcode 6 beta 2 compiler without error. The intention is to end up with an array of 24 "WaterUsage" classes all set to nil.
When I try to set an array element:
usage[hour] = usage
where hour is < 24 I get the error:
"WaterUsage doesn't have a member named subscript"
I've also tried using generics but that doesn't appear to work either.
I find the Swift syntax for using optionals in complex data structures is a little obscure and could use some advice here.
That way of defining the array is giving you an Optional array of Optional values ( WaterUsage?[]? ), which you have to unwrap before you can use. I think you want just the values to be optional: WaterUsage?[]. One way I've been able to do that is by using the generic Array syntax:
var usage: WaterUsage?[] = Array<WaterUsage?>(count:24, repeatedValue:nil)
usage[hour] = something
Another way is to force unwrapping of the return value of your initial declaration. I don't know why, but WaterUsage?[]() has an Optional return value.
var usage = (WaterUsage?[](count:24, repeatedValue:nil))!
usage[hour] = something
You're pretty close! When using the MemberType[] syntactic sugar for arrays, the way that you wrote it (WaterUsage?[]) actually declares the Array as Optional, as well as the values that it holds. In which case, to assign a value to an index you would need to unwrap the Array first by using:
usage![hour] = someWaterUsage
However, if you only want Optional members in the Array (and don't want the Array itself to be optional), then you can fall back to the standard Array declaration:
var usage = Array<WaterUsage?>(count:24, repeatedValue:nil)
edit:
I originally offered an alternate syntax as another solution as well:
var usage = (WaterUsage?)[](count:24, repeatedValue:nil)
...but in doing so, per #Nate's observations it then becomes the case that you need to use unwrapping twice to access the value at a specific index, for example:
usage[0]!!.someProperty
this is just a shot in the dark, but I think what may be happening in this case is not dissimilar at all to what OP originally tried with declaring the Array using WaterUsage?[]
that is, when using (WaterUsage?)[], perhaps it is seeing this declaration as an Array of Optional Tuples holding Optional WaterUsages, requiring us then to unwrap the member at the index twice before we can access its properties
interesting stuff!

Resources