Trying to append text to a property inside a loop in Swift - ios

I have an array of struct objects. These objects have a property for title (which is a String), and a property for location (of type Location).
What I would like to is append a double value for distance derived from the location property and the distance function with another, existing Location object, to the title property. Here is the code I am working with:
self.myList.map({$0.title.append("\($0.location.distance(from: location!)/1000)")})
The problem here is that the map function returns a new array, however, I need to make the change to the existing array, since I'm using this array as the datasource for my UITableView. The other problem is that despite me making the title property a var, I am always told the following error message:
Cannot use mutating member on immutable value: '$0' is immutable.
Can anyone figure out how to do this?

You should iterate over the array like this:
for (i, _) in myList.enumerated() {
myList[i].title.append("\(myList[i].location.distance(from: location) / 1000)")
}

You'd have to use a temporary mutable variable:
myList = myList.map { (myStruct: MyStruct) -> MyStruct in
var mutableStruct = myStruct
mutableStruct.title.append("\(element.location.distance(from: location) / 1000)")
return mutableStruct
}

Related

Appending items to an array in dictionary not working

I have this static dictionary created as so:
static var pictures = Dictionary<Int, Array<UIImage>>()
I want to populate it with images. At the moment when I am creating it I don't know how many key/value pairs I need to create. I have to fetch from the internet the data, but after that I am doing this to populate, but still my dictionary is empty:
for i in 0...Fetching.numberOfAliveListings - 1 {
for _ in 0...AdsCollectionView.listings[i].photos.count - 1 {
AdsCollectionView.pictures[i]?.append(UIImage(named: "noimage")!)
}
}
pictures is initially empty. So any attempt to access a value for a given key will result in a nil value. Since the value (the array) is nil, the optional chaining skips the call to append.
One solution is to provide a default array when looking up the value for a given Int.
AdsCollectionView.pictures[i, default: []].append(UIImage(named: "noimage")!)
You may also wish to consider alternate syntax when declaring pictures:
static var pictures = [Int: [UIImage]]()

Swift - Map to different type

Suppose that I have a text and an array of NSRanges. From that, I want to produce an array of substrings. What I would like to do is to use a simple map function and get done with it:
let substrings = ranges.map { return (text as NSString).substringWithRange($0) }
Swift won't actually compile this as it expects that the return type of the function to be applied by the map to be the same as the array's type. Is there any way to map those values to a different type?
The map closure does not need a return statement.
let substrings = ranges.map { (text as NSString).substringWithRange($0) }
EDIT: The return statement appears to be implicit if you leave it out. So your code should work as it is. What is your error?

How to remove an element of a given custom type value from an array in Swift

I want to remove element of custom type value from an array.
I want to pass a variant instance to function to remove it from array, I don't want to use removeAtIndex().
var favoriteVariants: [Variant]
func removeVariant(variant: Variant)
{
}
If Variant is Equatable and you only want to remove the first one that matches:
if let idx = favoriteVariants.indexOf(variant) {
favoriteVariants.removeAtIndex(idx)
}
If it isn’t Equatable and you have some other matching criteria to find just one to remove:
let idx = favoriteVariants.indexOf {
// match $0 to variant
}
if let idx = idx {
favoriteVariants.removeAtIndex(idx)
}
(these are assuming Swift 2.0 – if 1.2, it’s find(favoriteVariants, variant) instead of indexOf, and there isn’t a version that takes a closure, though it’s not too hard to write one)
If there are multiple ones you want to remove in one go:
favoriteVariants = favoriteVariants.filter {
// criteria to _keep_ any given favorite
}
All of these could be wrapped in extensions if what you want to do is general enough to justify it.

"Cannot assign to" error iterating through array of struct

I have an array of structs:
struct CalendarDate {
var date: NSDate?
var selected = false
}
private var collectionData = [CalendarDate]()
Which I simply populate with a date like this:
for _ in 1...7 {
collectionData.append(CalendarDate(date: NSDate(), selected: false))
}
So when you tap on a collectionView, I simply want to loop through the data and mark them all as False.
for c in collectionData {
c.selected = false ///ERROR: Cannot assign to 'selected' in 'c'
}
Why do I get this error?
If I do this, it works fine but I want to know what I did wrong above:
for i in 0..<collectionData.count {
collectionData[i].selected = false
}
As I understand it, the iterator
for c in collectionData
returns copies of the items in collectionData - (structs are value types, not reference types, see http://www.objc.io/issue-16/swift-classes-vs-structs.html), whereas the iteration
for i in 0..<collectionData.count
accesses the actual values. If I am right in that, it is pointless to assign to the c returned from the iterator... it does not "point" at the original value, whereas the
collectionData[i].selected = false
in the iteration is the original value.
Some of the other commentators suggested
for (var c) in collectionData
but although this allows you to assign to c, it is still a copy, not a pointer to the original, and though you can modify c, collectionData remains untouched.
The answer is either A) use the iteration as you originally noted or B) change the data type to a class, rather than a struct.
because each 'c' is by default let, and this is a new instance of CalendarDate and the value of array at index copied to this for each step of for, and 'c' isn't pointer to the index of the array and it is just a copy of index, so if you set a new value to this, the new value does not apply in array.
but 'i' is used as index of array and can directly manipulate the values of array.
If you are using structs they are copies in the array. So even changing them only changes the copy, not an actual object in the array.
You have to make them a variable in the loop to be editable copy, and reassign them into the array right back.
If they are classes and not structs, than you don't have to reassign part, just do the var thing.
for (index, var c) in collectionData.enumerated() {
c.selected = false
collectionData[index] = c
}

How to create a mutable array of specific class type in Swift

I have a class called Bullet and I want to make a mutable array with this class type. Basically the desired outcome I want is, when a user touches the screen a new bullet is spawned. I know in Java you can use an ArrayList to achieve this by adding a new instance to the array list each time.
I'm not sure syntactically how I could achieve in Swift or if it is even possible.
This is the code I have for declaring and instance of the Bullet class but how do I make it so that it is a mutable array...
var bullet: Bullet = Bullet()
Thank you!
Its simple :
var bulletArray = [Bullet]() // this will declare and initialize the bulletArray
In the above line of code the type is inferred for the bulletArray.
If you explicitly want to specify the type then,
var bulletArray:[Bullet] = [Bullet]() // this will declare and initialize the bulletArray
If you just want to declare the array but not initialize then
var bulletArray:[Bullet]
If you just declare the array then you need to initialize it in init() before using it. Or else you can declare array as optional type. As shown below,
var bulletArray: [Bullet]?
HTH :)
To create a typed array...
var bulletArray: [Bullet] = []
A mutable array in Swift is an array with a mutable reference:
var bulletList = [Bullet]()
Now you can add Bullet objects at will...

Resources