Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS Enhance a Weather App with Table Views Next Week’s Weather Working With Dates and Times

Reed Carson
Reed Carson
8,306 Points

Guard Statements in Initializer fail to initialize all values

I followed this course after 2.0 came out so instead of using if let I used guard statements just to practice doing so. Im familiar with them, use them all the time and know the proper syntax. However I was pulling my hair out because there was one error at the bottom of my initializer: "return from initializer without initializing all stored properties".

I even set the values to nil in the else part of the guard just in case, but it still wouldn't compile. I quadruple checked multiple times that I had everything set. The only difference in code was my use of guard statements. Is this a known issue?

struct DailyWeather {

    let maxTemp: Int?
    let minTemp: Int?
    let humidity: Int?
    let precipChance: Int?
    var summary: String?
    var icon: UIImage? = UIImage(named: "default.png")
    var largeIcon: UIImage? = UIImage(named: "default_large.png")
    var sunriseTime: String?
    var sunsetTime: String?
    var day: String?

    let dateFormatter = NSDateFormatter()

    init(dailyWeatherDictionary: [String:AnyObject]) {

        minTemp = dailyWeatherDictionary["temperatureMin"] as? Int
        maxTemp = dailyWeatherDictionary["temperatureMax"] as? Int
        guard let humidityFloat = dailyWeatherDictionary["humidity"] as? Double else { humidity = nil ; return }
        humidity = Int(humidityFloat * 100)
        guard let precipFloat = dailyWeatherDictionary["precipProbability"] as? Double else { precipChance = nil ; return }
        precipChance = Int(precipFloat * 100)
        summary = dailyWeatherDictionary["summary"] as? String
        guard let
            iconString = dailyWeatherDictionary["icon"] as? String,
            iconEnum = Icon(rawValue: iconString) else { icon = nil ; largeIcon = nil ; return }
        (icon, largeIcon) = iconEnum.toImage()

        guard let sunriseDate = dailyWeatherDictionary["sunriseTime"] as? Double else { sunriseTime = nil ; return }
        sunriseTime = timeStringFromUnixTime(sunriseDate)
        guard let sunsetDate = dailyWeatherDictionary["sunsetTime"] as? Double else { sunsetTime = nil ; return }
        sunsetTime = timeStringFromUnixTime(sunsetDate)
        guard let time = dailyWeatherDictionary["time"] as? Double else { day = nil ; return }
        day = dayStringFromUnixTime(time)

    }
    (methods follow)

1 Answer

Michael Hulet
Michael Hulet
47,913 Points

All properties have to be initialized before any guard statementreturns. Thus, you make sure that every property is initialized before theelsestatement of anyguardstatement finishes. A perhaps faster and easier solution would be to make the initializer itself fail if any of theguardstatements do. You can do this by making theinitreturn an Optional, andreturn nilin theguard`s where something goes wrong, like this:

init(dailyWeatherDictionary: [String: AnyObject])?{
  //Initialize stuff
  guard someProperty = dailyWeatherDictionary["someKey"] else{ return nil }
  // Initialize more stuff, in case the above guard succeeds
  //Repeat as necessary
}