Search code examples
iosarraysswiftuilabel

How can I check how many itens I have in an array and assign each one of them to a label in Swift?


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)

error message

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)
        }

...


Solution

  • 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