In Objective-C I would write:
#property (nonatomic, strong) NSMutableArray *privateArray;
if (!self.privateArray) {
// Populate the privateArray
}
Which checks that an array does not already exists before populating it. How could this be achieved in Swift?
I have tried implementing it by translating my Obj-C code but am given an Xcode error "Unary operator '!' can not be applied to an operand of type '[AnyObject]'"
Swift attempt:
private var privateArray: [AnyObject]?
if !privateArray {
// Populate the array
}
How would I check if the array exists before populating the array, in Swift?
Is it just as simple to use .isEmpty on the array?
Thanks in advance!
In Objective-C this is called lazy loading. You declare a property but only create the property the first time it is accessed.
The trap you have fallen into is thinking that Swift is just a different syntax around Objective-C.
In Swift you can have a lazy var...
You can declare it like this...
#lazy var someArray: [String] = {
return ["Hello", "World"]
}
This will do what you want.
As a side note. It's generally not a good idea to use AnyObject especially if you know the type of object the array will contain.
Also, by using this method you don't need the array to be optional and so can avoid the whole unwrapping thing.
You can read more about lazy properties by googling it. I found this and it looks quite good... http://mikebuss.com/2014/06/22/lazy-initialization-swift/
You should write:
if (privateArray == nil) {
// Populate the array
}
Related
as the title says, I wish to create a variable which is an array list of hash maps where key is a string and value is another array list of objects of custom class.
In Swift or other languages it will look something like this:
[String: [MyClass]]
In Kotlin I tried:
var testVar = ArrayList<HashMap<String, ArrayList<MyClass>>()>
I am seeing error like "Expecting a '>', Property getter or setter expected".
What am I doing wrong here?
I think this is a simple typo: your parentheses are inside the third closing angle bracket, and should be outside:
var testVar = ArrayList<HashMap<String, ArrayList<MyClass>>>()
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.
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
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...
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!