I have a weather app which have an stack to display 8 days forecast with 8 labels, one for each day and this data came from an array created from a json data. Sometimes API returns less than 8 days and app crashes with fatal error: Index out of range.
Could you please help me to find a way to for example check how many days have been received from the API and assign the date to each label only for the received days and put "N/A" into the label that has no data from the array ?
Any other suggestion is welcome.
Below my ViewController where the error occurs and the function to convert the date and get only the day:
@IBOutlet weak var day1Label: UILabel!
@IBOutlet weak var day2Label: UILabel!
@IBOutlet weak var day3Label: UILabel!
@IBOutlet weak var day4Label: UILabel!
@IBOutlet weak var day5Label: UILabel!
@IBOutlet weak var day6Label: UILabel!
@IBOutlet weak var day7Label: UILabel!
@IBOutlet weak var day8Label: UILabel!
...
self.day1Label.text = dtString(dt: weather.dailyArray[0].dt)
self.day2Label.text = dtString(dt: weather.dailyArray[1].dt)
self.day3Label.text = dtString(dt: weather.dailyArray[2].dt)
self.day4Label.text = dtString(dt: weather.dailyArray[3].dt)
self.day5Label.text = dtString(dt: weather.dailyArray[4].dt)
self.day6Label.text = dtString(dt: weather.dailyArray[5].dt)
self.day7Label.text = dtString(dt: weather.dailyArray[6].dt)
self.day8Label.text = dtString(dt: weather.dailyArray[7].dt)
...
func dtString(dt: Double) -> String {
let df = DateFormatter()
df.locale = NSLocale.current
df.dateFormat = "dd"
let day = Date(timeIntervalSince1970: dt)
let dayString = df.string(from: day)
return dayString
}
Update:
I created an Outlet array and I was looking for something like below to have each value from the array to be assigned in a for loop to each label but another issue is presented.
...
@IBOutlet private var dayLabels: [UILabel]!
...
let days = weather.dailyArray.count
for days in weather.dailyArray {
self.dayLabels[days] = dtString(dt: weather.dailyArray[days].dt)
}
self.dayLabels[0].text = dtString(dt: weather.dailyArray[0].dt)
Fixed:
...
@IBOutlet private var dayLabels: [UILabel]!
...
func dtString(dt: Double) -> String {
let df = DateFormatter()
df.locale = NSLocale.current
df.dateFormat = "dd"
let day = Date(timeIntervalSince1970: dt)
let dayString = df.string(from: day)
return dayString
}
...
let totalDays = weather.dailyArray.count
for days in 0...totalDays - 1 {
self.dayLabels[days].text = dtString(dt: weather.dailyArray[days].dt)
}
...
Get the length of an array with count
:
let days = weather.dailyArray.count
then just check to see if the index is out of range:
if days > 7 {
self.day8Label.text = dtString(dt: weather.dailyArray[7].dt)
} else {
self.day8Label.text = "N/A"
}
Regarding your second issue, you cannot a UILabel
to a String
. You will have to use the .text
property on the UILabel
as done in my previous example code.
So self.dayLabels[days]
should be self.dayLabels[days].text