I am completely new in swift and iOS developing.
I want to initialize this array
I defined the array like this when my class starts
var i = 0
var ArrayTitle = [NSString]()
and then I need to initialize it in one of the functions like this
let ArrayTitl[i] = "text"
and I checked it even like this but the error is same
let ArrayTitl[0] = "text"
but it has this Error
Cannot assign to immutable expression of type '[Int]'
Appreciate any help. thanks
You are using a dynamic array so you need to append the value.
Here's a small exemple:
var arrayTitle = [String]()
arrayTitle.append("text")
print(arrayTitle[0]);
Related
I have a variable on my class:
var list = []
and I use it on a function of my class:
func chargeData (data: NSArray){
list = data
}
It worked well on my project in Swift 2.3 but when I have updated it to XCode8 and Swift3 it gives to me the following error:
Empty collection literal requires an explicit type
so I have added a typecast to my list variable:
var list = [] as! NSArray
but it gives to me the following alert:
Forced cast of 'NSArray' to same type has no effect
I know that an alert does not broke the application but I would like to solve this error in a proper way.
Did someone got the same error and solved it properly?
Thanks in advance!
This error occurs since implicit conversions are abolished so you have to tell the compiler the explicit type (of the ArrayLiteral []):
var list: NSArray = []
// or
var list = [] as NSArray
The Swift 5 guided tour is pretty explicit about creating empty arrays or dictionaries: https://docs.swift.org/swift-book/GuidedTour/GuidedTour.html#ID461 towards the end of the first section.
To create an empty array or dictionary, use the initializer syntax.
let emptyArray = [String]()
let emptyDictionary = [String: Float]()
Update swift 4 :
var array = [] as [String]
You are mixing ObjectiveC (NSArray) and Swift (Array<T>). Items inside an NSArray are assumed to be NSObject and its subclasses, while Swift has no clue what T is since the array is empty and hence type inference doesn't work.
If you declare it like this:
var data: NSArray = []
there will be a conflict since var means mutable in Swift, but NSArray is immutable in ObjC. You can get around that by changing it to NSMutableArray, which is a subclass of NSArray:
let data = NSMutableArray() // note that we don't need var here
// as NSMutableArray is already mutable
If you want to keep data as Swift's Array, give it a type:
var data = [MyDataModel]()
// or
var data = [AnyObject]()
// usage:
chargeData(data: data as NSArray)
I’m new to Swift and have been having some troubles figuring out some aspects of Arrays and Dictionaries.
I have an array of dictionaries, for which I have used Type Aliases - e.g.
typealias myDicts = Dictionary<String, Double>
var myArray : [myDicts] = [
["id":0,
"lat”:55.555555,
"lng”:-55.555555,
"distance":0],
["id":1,
"lat": 44.444444,
"lng”:-44.444444,
"distance":0]
]
I then want to iterate through the dictionaries in the array and change the “distance” key value. I did it like this:
for dict:myDicts in myArray {
dict["distance"] = 5
}
Or even specifically making sure 5 is a double with many different approaches including e.g.
for dict:myDicts in myArray {
let numberFive : Double = 5
dict["distance"] = numberFive
}
All my attempts cause an error:
#lvalue $T5' is not identical to '(String, Double)
It seems to be acting as if the Dictionaries inside were immutable “let” rather than “var”. So I randomly tried this:
for (var dict:myDicts) in myArray {
dict["distance"] = 5
}
This removes the error and the key is indeed assigned 5 within the for loop, but this doesn't seem to actually modify the array itself in the long run. What am I doing wrong?
The implicitly declared variable in a for-in loop in Swift is constant by default (let), that's why you can't modify it directly in the loop.
The for-in documentation has this:
for index in 1...5 {
println("\(index) times 5 is \(index * 5)")
}
In the example above, index is a constant whose value is automatically
set at the start of each iteration of the loop. As such, it does not
have to be declared before it is used. It is implicitly declared
simply by its inclusion in the loop declaration, without the need for
a let declaration keyword.
As you've discovered, you can make it a variable by explicitly declaring it with var. However, in this case, you're trying to modify a dictionary which is a struct and, therefore, a value type and it is copied on assignment. When you do dict["distance"] = 5 you're actually modifying a copy of the dictionary and not the original stored in the array.
You can still modify the dictionary in the array, you just have to do it directly by looping over the array by index:
for index in 0..<myArray.count {
myArray[index]["distance"] = 5
}
This way, you're sure to by modifying the original dictionary instead of a copy of it.
That being said, #matt's suggestion to use a custom class is usually the best route to take.
You're not doing anything wrong. That's how Swift works. You have two options:
Use NSMutableDictionary rather than a Swift dictionary.
Use a custom class instead of a dictionary. In a way this is a better solution anyway because it's what you should have been doing all along in a situation where all the dictionaries have the same structure.
The "custom class" I'm talking about would be a mere "value class", a bundle of properties. This was kind of a pain to make in Objective-C, but in Swift it's trivial, so I now do this a lot. The thing is that you can stick the class definition for your custom class anywhere; it doesn't need a file of its own, and of course in Swift you don't have the interface/implementation foo to grapple with, let alone memory management and other stuff. So this is just a few lines of code that you can stick right in with the code you've already got.
Here's an example from my own code:
class Model {
var task : NSURLSessionTask!
var im : UIImage!
var text : String!
var picurl : String!
}
We then have an array of Model and away we go.
So, in your example:
class MyDict : NSObject {
var id = 0.0
var lat = 0.0
var lng = 0.0
var distance = 0.0
}
var myArray = [MyDict]()
let d1 = MyDict()
d1.id = 0
d1.lat = 55.55
d1.lng = -55.55
d1.distance = 0
let d2 = MyDict()
d2.id = 0
d2.lat = 44.44
d2.lng = -44.44
d2.distance = 0
myArray = [d1,d2]
// now we come to the actual heart of the matter
for d in myArray {
d.distance = 5
}
println(myArray[0].distance) // it worked
println(myArray[1].distance) // it worked
Yes, the dictionary retrieved in the loop is immutable, hence you cannot change.
I'm afraid your last attempt just creates a mutable copy of it.
One possible workaround is to use NSMutableDictionary:
typealias myDicts = NSMutableDictionary
Have a class wrapper for the Swift dictionary or array.
class MyDictionary: NSObject {
var data : Dictionary<String,Any>!
init(_ data: Dictionary<String,Any>) {
self.data = data
}}
MyDictionary.data
I'm pretty new to Swift and need your help on a (probably) pretty basic problem.
I have a dictionairy:
var dict = ["title" : "Title", "Features" : ["feat1", "feat2", "feat3"], ...]
I can create a string from it like so:
var headline = dict["title"]! as string
but I couldn't manage to create an array. I tried in various combinations:
var features = dict["Features"]
var features = dict["Features"]! as Array
var features: Array = dict["Features"]
So please enlighten me! How do create an array? Is it possible at all?
You should specify the type for the array. Either
let features = dict["Features"] as [String]
or
let features = dict["Features"] as Array<String>
See the discussion of collection types in The Swift Language.
Your problem is that you don't have a type for the array. You describe the type of an array in swift by putting the type name in brackets. In your case, this will be [String]. Thus, your code should be var features = dict["Features"] as [String] for a mutable array, or use let for an immutable array. Hope this helps.
In the Swift PDF file released by Apple i came thorough this code
To create an empty array or dictionary, use the initializer syntax.
let emptyArray = [String]()
let emptyDictionary = [String: Float]()
Here what is the use of creating a let (constant) object with empty array, where we cannot insert any values into it in next line ??!!
while teaching objective- c they start teaching like
NSArray *arrayObj = [[NSArray alloc] init]
if we declare like this we cannot add objects after initialisation
similarly they are teaching us how to initialise an array or dictionary objects
one more difference is if we allocate an empty array then we can assign another array with this.
let will not allow you to assign another array to it also
let emptyArray = [String]()
let/var filledArray = ["stack", "overflow"]
emptyArray = filledArray // will give you an error
Not much use, but the value can be copied:
let emptyDictionary = [String: Float]()
var otherDictionary = emptyDictionary
otherDictionary["a"] = 0.5
The property declaration sets them to a default, but you could actually change the value to something else in init. This would only be the case for class properties, not inline properties though.
Here's an example in a class scope where a let property can have a default but be changed:
class Whatever {
let testArray = [Int]()
init() {
testArray = [0,1,2]
}
}
I have a dictionary set up as:
var jDict = Dictionary<String, AnyObject[]>()
Where the arrays are either a collection of custom buttons (JunkButton) or Labels (JunkLabels).
I am having an issue when trying to access the members of the arrays contained in the Dictionary as follows:
let thisArray = jDict[key]
var aButton = thisArray[0] //Gives error: 'AnyObject[]? does not have a member named 'subscript'
I can get around this by downcasting the whole array as follows:
if let aArray = thisArray as? JunkButton[]{
var aButton = aArray[0]
}
This seems very cumbersome especially if I am sure I know what type the array is made up of beforehand. Is there a way to cast thisArray when it is created that would allow me to extract its elements without unwrapping them each time?
Dictionary always give you Optional value.
Your code is like this
let thisArray : Optional<AnyObject[]> = jDict[key]
You need to unwrap it to get non-optional value
let thisArray = jDict[key]! // thisArray is AnyObject[]
You really shouldn't use a dictionary for this. Swift makes it very easy to use custom little structs or classes instead of dictionaries:
struct JunkItems {
var buttons: [JunkButton] = []
var labels: [JunkLabel] = []
}
Then you can access those items like this without downcasting:
for button in junkItems.buttons {
// ...
}
Or:
if let button = junkItems.buttons[0] {
// ...
}
Btw, the array notation [JunkButton] is new in beta 3.