Swift - Append object: array index out of range - arrays

When I try to add an item to my array it gives me and EXC BAD INSTRUCTION error and it says
fatal error: Array index out of range
That is the code:
var tabelle : [[Actions]] = [[]]
func doSomething() {
var results = self.fetch()
var oldProjektName: String = results[0].projektName
var count: Int = 0
for item in results {
if oldProjektName == item.projektName {
tabelle[count].append(item)
} else {
count++
tabelle[count].append(item)
}
oldProjektName = item.projektName
}
}
As long as count = 0 it does not give me an error but when count = 1 then the app crashes.

You have an array with one element: var tabelle : [[Actions]] = [[]]
That is why tabelle[0] is working.
You need to append another array to tabelle before you can use tabelle[1]

Try
var tabelle = [[Actions]](())

Related

Get values from a textfield array

I would like to access the values of my textfield array but confused as the array I created is with tags.
So anyone knows how to get the value of the list (array) I created?
I want to create a function where I :
Get the value of the textfields on a list
Sort them by tags
get the value of each individual textfield
concatenate them in a string
1.Your collection Outlet will be something like this
#IBOutlet var textFields: [UITextFields]!
2. Sort it by tag
textFields.sort { $0.tag < $1.tag}
3. Use for loop to get value from array and concatenate it
var string = ""
for item in textFields {
string += item.text
}
Let's say you have following array,
var txtArray:[UITextField] = [UITextField]()
for i in 0...4 {
let txtField = UITextField(frame: .zero)
txtField.text = "\(i)"
txtField.tag = i
txtArray.append(txtField)
}
To get values you have to do following,
let sorted = txtArray.sorted { $0.tag < $1.tag }
let values = sorted.map { return $0.text! }
let test = values.joined(separator: " ")
print(test)
Output will be
0 1 2 3 4
Create an outlet connection and connect all your textfields to the same.
An outlet connection looks like
#IBOutlet strong var labels: [UILabel]!
Then to get all textfield contents and to append the same.
var resultString = ""
for item in enumerate(self.labels) {
resultString = resultString + item.text
}
Assume that you have array of UITextField
let textfield1 = UITextField()
textfield1.tag = 1
textfield1.text = "1"
let textfield2 = UITextField()
textfield2.tag = 2
textfield2.text = "2"
let textfield3 = UITextField()
textfield3.tag = 3
textfield3.text = "3"
let arrayOfTextFields :[UITextField] = [textfield2,textfield1,textfield3]
let result = self.getInputsValue(arrayOfTextFields, seperatedby: "-")
print(result)
Method you want :
func getInputsValue(_ inputs:[UITextField], seperatedby value: String) -> String {
return inputs.sorted {$0.tag < $1.tag}.map {$0.text}.compactMap({$0}).joined(separator: value)
}
Result:
1-2-3

Find element in an array of object

I created an array of objects:
var fullMonthlyList = [SimulationMonthly]()
The class here:
class SimulationMonthly {
var monthlyMonthDuration: NSNumber = 0
var monthlyYearDuration: NSNumber = 0
var monthlyFullAmount: NSNumber = 0
var monthlyAmount: Int = 0
init(monthlyMonthDuration: NSNumber, monthlyYearDuration: NSNumber, monthlyFullAmount: NSNumber, monthlyAmount: Int){
self.monthlyMonthDuration = monthlyMonthDuration
self.monthlyYearDuration = monthlyYearDuration
self.monthlyFullAmount = monthlyFullAmount
self.monthlyAmount = monthlyAmount
}
}
I just did append to populate it, now I want to find for example if they're an existing value, for example monthlyAmount equals to "194" by search in the array, how can I do ? I have tried filter and contains but I get errors.
What I've tried:
if self.fullMonthlyList.filter({ $0.monthlyAmount == self.monthlyAmount.intValue }) { ... }
Error:
Cannot invoke 'filter' with an argument list of type '((SimulationMonthly) throws -> Bool)'
You can do:
if let sim = fullMonthlyList.first(where: { $0.monthlyAmount == 194 }) {
// Do something with sim or print that the object exists...
}
This will give you the first element in your array where monthlyAmount equals 194.
If you want all elements with that condition, you can use filter:
let result = fullMonthlyList.filter { $0.monthlyAmount == 194 }
If you don't need the object at all but you just want to know if one exists, then contains would be enough:
let result = fullMonthlyList.contains(where: { $0.monthlyAmount == 194 })
Here's a simple playground example of filtering objects based on matching a property. You should be able to expand it to your situation.
class Item {
var value: Int
init(_ val: Int) {
value = val
}
}
var items = [Item]()
for setting in 0..<5 {
items.append(Item(setting))
}
func select(_ with: Int) -> [Item] {
return items.filter { $0.value == with }
}
let found = select(3)

How to append custom object to an array in Swift?

How to append custom class object to an array in Swift?
Below is my code, but it shows error.
Error:
"Cannot assign value of '()' to type [PhotoVC]"
Code:
var photoVCs = [PhotoVC]()
for index in 0 ..< photos.count {
if let vc = getPhotoController(index) {
photoVCs = photoVCs.append(vc)
}
}
func getPhotoController(index: Int) -> PhotoVC? {
if index < 0 || index == NSNotFound {
return nil
}
else if index == photos.count {
return nil
}
let PhotoVCID = "PhotoVCID"
if let storyboard = storyboard,
pageVC = storyboard.instantiateViewControllerWithIdentifier(PhotoVCID) as? PhotoVC {
pageVC.photoName = photos[index]
pageVC.photoIndex = index
return pageVC
}
return nil
}
I should be able to do it, but what's the problem?
append does not return anything. Remove the assignment:
photoVCs = photoVCs.append(vc) // wrong
photoVCs.append(vc) // ok

Swift: using a for loop to insert items. At the end, when i query it shows only the value which was inserted last at each index

In Swift playground, I'm using a for loop to insert items. During the loop it seems to be adding the right values. At the end of the for loop, when the array is all filled up, when I query, it shows only the value which was inserted last at each index.
New to swift, so I guess am doing something really stupid here... Need help...
The code is as below:
class card {
var suit: String = ""
var rank: String = ""
}
var card1 = card()
var deck = [card]()
var playingCard = card()
var suits = ["♠︎","♣︎","♥︎","♦︎"]
var ranks = ["A","K","Q","J","10","9","8","7","6","5","4","3","2"]
let countRanks = ranks.count
let countSuits = suits.count
var ctr = 0
for i in 0..<countSuits {
for j in 0..<countRanks {
playingCard.rank = ranks[j]
playingCard.suit = suits[i]
deck.insert(playingCard, atIndex: 0)
println("\(deck[ctr].suit)"+"\(deck[ctr].rank)")
ctr++
}
}
let x = deck.count
for i in 0..<x {
println("\(deck[i].rank)"+"\(deck[i].suit)")
}
class instances are reference types. You need to create a new card instance for each iteration. Move the line var playingCard = card() right after the for j in 0..<countRanks line and change var to let
You need to initialise a new instance of playingCard each iteration:
for i in 0..<countSuits {
for j in 0..<countRanks {
var playingCard = card()
...
}
}
I would also suggest you add an init method for your card class to make it easier to initialise:
class Card {
var suit: String
var rank: String
init(suit: String, rank: String) {
self.suit = suit
self.rank = rank
}
}
...
var playingCard = Card(suit: suits[i], rank: ranks[j])

Arrays and Swift

I'm trying to deal with an app in Swift and I'm facing the following error using arrays:
fatal error: Array index out of range
This appears when apps assign a value to the array at index 0:
class DrawScene: SKScene {
init(size: CGSize) {
super.init(size: size)
}
var line = SKShapeNode()
var path = CGPathCreateMutable()
var touch: UITouch!
var pts = [CGPoint]()
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */
touch = touches.anyObject() as UITouch!
self.pts[0] = touch.locationInNode(self) <-- Error appears here
drawLine()
}
Some ideas? (I'm using xcode 6 Beta 4)
Your array is empty at first.
if self.pts.isEmpty {
self.pts.append(touch.locationInNode(self))
}
else {
self.pts[0] = touch.locationInNode(self)
}
As it says in the docs:
“You can’t use subscript syntax to append a new item to the end of an array. If you try to use subscript syntax to retrieve or set a value for an index that is outside of an array’s existing bounds, you will trigger a runtime error.”
You'll have to use append or += to add to an empty array. If you always want to set this point to the first object in the array, replacing anything already there, you'll have to check the count of the array first.
I don't recommend this to anyone, but you could implement your own subscript that allows you to do this:
extension Array {
subscript(safe index: Int) -> Element? {
get {
return self.indices.contains(index) ? self[index] : nil
}
set(newValue) {
guard let newValue = newValue { return }
if self.count == index {
self.append(newValue)
} else {
self[index] = newValue
}
}
}
}
And you can use this as expected:
var arr = [String]()
arr[safe: 0] = "Test"
arr[safe: 1] = "Test2"
print(arr) // ["Test", "Test2"]
arr[safe: 0] = "Test0"
print(arr) // ["Test0", "Test2"]
arr[safe: 3] = "Test2" // fatal error: Index out of range

Resources