Confused about Swift Array Declarations - arrays

Is there any difference between the following?
var array1_OfStrings = [String]()
var array2_OfStrings: [String] = []
var array3_OfStrings: [String]
Testing in Playground shows that 1 and 2 are the same but 3 behaves differently.
Can someone explain me the difference please? And also what will be the preferred way to declare an empty array of String?

First two have the same effect.
declare a variable array1_OfStrings, let it choose the type itself. When it sees [String](), it smartly knows that's type array of string.
You set the variable array2_OfStrings as type array of string, then you say it's empty by []
This is different because you just tell you want array3_OfStrings to be type array of string, but not given it an initial value.
I think the first one is recommended as The Swift Programming Language uses it more often.

While I might be late to the party, there is one thing that needs to be said.
First option set array1_OfStrings to array of Strings
The other option tells that array1_OfStrings is array of Strings and then set it empty.
While this might be a really small difference, you will notice it while compiling. For the first option compiler will automatically try to find out what is the type of array1_OfStrings. Second option won't do that, you will let compiler know that this actually is array of Strings and done deal.
Why is this important? Take a look at the following link:
https://thatthinginswift.com/debug-long-compile-times-swift/
As you can see, if you don't declare type of your variable that might impact build performance A LOT.

Related

In Swift, What is the difference between var myArray: [myClass] and var myArray = [Array]() [duplicate]

Is there any difference between the following?
var array1_OfStrings = [String]()
var array2_OfStrings: [String] = []
var array3_OfStrings: [String]
Testing in Playground shows that 1 and 2 are the same but 3 behaves differently.
Can someone explain me the difference please? And also what will be the preferred way to declare an empty array of String?
First two have the same effect.
declare a variable array1_OfStrings, let it choose the type itself. When it sees [String](), it smartly knows that's type array of string.
You set the variable array2_OfStrings as type array of string, then you say it's empty by []
This is different because you just tell you want array3_OfStrings to be type array of string, but not given it an initial value.
I think the first one is recommended as The Swift Programming Language uses it more often.
While I might be late to the party, there is one thing that needs to be said.
First option set array1_OfStrings to array of Strings
The other option tells that array1_OfStrings is array of Strings and then set it empty.
While this might be a really small difference, you will notice it while compiling. For the first option compiler will automatically try to find out what is the type of array1_OfStrings. Second option won't do that, you will let compiler know that this actually is array of Strings and done deal.
Why is this important? Take a look at the following link:
https://thatthinginswift.com/debug-long-compile-times-swift/
As you can see, if you don't declare type of your variable that might impact build performance A LOT.

Difference between these arrays as member variable of view controller

I would like to have an array as a member of my table view controller. The array will be a data source.
What are the differences or advantages/disadvantages the following ways of having a member variable array.
class BinViewController: UITableViewController, WKNavigationDelegate {
var peopleArray1 = [String]()
var peopleArray2: [String] = []
var peopleArray3: [String]!
var peopleArray4: [String]?
I think there is not the right question that you need to ask yourself. There is no advantage or disadvantage. There are ways to initialize a member of a class based on what you need and your logic that you want to implement.
var peopleArray1 = [String]() you are saying to the compiler please let me create an empty array of string. It's declared and initialized. Also you let the compiler to infer the type of your array compared to your second statement.
var peopleArray2: [String] = [] it's 99% the same thing as your first statement. You are creating en empty array of String. Declared and initialized. Here the only difference is that you specify the type of your array. You don't let the compiler to infer the type of your array. var variable:TypeVariable = .... It's recommended by Apple to let the compiler to infer the type of your variables members when you can because you win a readable code
var peopleArray3: [String]! it's pretty different than your previous 2 initializations. First, you need to know that Swift is a very strongly typed language and you need to initialize every variable before using it. One thing that you can experiment is try to make the same statement without the ! or ? and you will your compiler warned you with an issue. Sometimes you just don't know what is the initial value but you are sur that at one moment, you will have a value. A variable is these two possible states : no value or a value are called Optionals. With this statement you are saying i want to create an array of string that might be nil or might have some String values. If you print your array you will have a message like "Optional([String])". To get the value of your Optional you need to unwrap it with the exclamation mark only when you are sure that you have a value. If not, your program is going to crash. Here with this initialization, you are saying to the compiler to not be worried because you know that in the future your array is going to have some values.
var peopleArray4: [String]? is the same as the previous one. The main difference is that everytime you want to access peopleArray values you will need to put an exclamation mark to unwrap his value.
There is no advantage/disadvantage just logic to use Optionals. If your array might be nil and further have values or is it a static array...
These two basically do the same thing:
var peopleArray1 = [String]()
var peopleArray2: [String] = []
They declare and initialize an empty array of type [String].
These two in the other hand, are also similar:
var peopleArray3: [String]!
var peopleArray4: [String]?
The array itself for both of them could be nil, which they currently are as they are declared.
The difference is that peopleArray3 is an implicitly unwrapped optional array of Strings, while peopleArray4 is an optional array of Strings.
What this means for peopleArray3 is that you're telling the complier that you will set a value to it before it's used. If you try to access it while its value is nil, the app will crash.
For peopleArray4, you're telling the compiler that the array might be nil at any time, so you'll need to check if peopleArray4 is not nil before you access it.

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)

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