0

There was a similarly named topic but the example was an error due to user mistake. I believe this example is an actual XCode issue.

I was following a treehouse tutorial and in the spirit of swift 2.0 I used guard statements instead of if lets in the initializer. My code was identical to the instruction except for the use of guard statements. It had one error that said "return from initializer without initializing all stored properties". Once I changed it to if let statements, it worked. Perhaps I made a mistake somewhere but I stared at it for atleast an hour, no properties were left un-initialized.

I made the properties equal to nil in the else clauses just in case but that didnt affect anything.

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)

}


func timeStringFromUnixTime(unixTime: Double) -> String {

    let date = NSDate(timeIntervalSince1970: unixTime)

    dateFormatter.dateFormat = "hh:mm a"
    return dateFormatter.stringFromDate(date)

}

func dayStringFromUnixTime(unixTime: Double) -> String {

    let date = NSDate(timeIntervalSince1970: unixTime)
    dateFormatter.locale = NSLocale(localeIdentifier: NSLocale.currentLocale().localeIdentifier)
    dateFormatter.dateFormat = "EEEE"
    return dateFormatter.stringFromDate(date)

  }
}
David Snabel
  • 9,801
  • 6
  • 21
  • 29
R.P. Carson
  • 439
  • 5
  • 20
  • add a breakpoint to your initializer then re-run your program... Step through your application until your initializer returns early, then you'll have your problem. – Dan Beaulieu Feb 14 '16 at 00:16
  • Also, a failed guard statement results in an early return, which in this case results in a failed initialization. If-let might be a better choice in this situation as its better to have an empty label than a failed initialization. – Dan Beaulieu Feb 14 '16 at 00:19
  • @DanBeaulieu ah, the early return I guess thats what it is, thank you. maybe they will add a better error message for that in the future? or would that have worked if i made it a failable init? – R.P. Carson Feb 14 '16 at 00:37
  • What about a failable initializer (`init?`) https://developer.apple.com/library/mac/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html – FranMowinckel Feb 14 '16 at 21:06

1 Answers1

0

let's have

struct S {
    var i: Int?
    init(b: Bool){
        guard b == false else { return }
        //if b == true { return }
        i = 0 // if b == true, this statement doesn't execute
    }
}

let s1 = S(b: true)
let s2 = S(b: false)
print(s1, s2) // S(i: nil) S(i: Optional(0))

because var i: Int? has a default value nil, even though i = 0 is not reachable if parameter of init is true, the compiler doesn't complain.

struct S {
    let i: Int?
    init(b: Bool){
        guard b == false else { return }
        //if b == true { return }
        i = 0 // if b == true, this statement doesn't execute
    }
}

will NOT compile, with error: return from initializer without initializing all stored properties and note: 'self.i' not initialized, because constant let i: Int? doesn't have any default value

Your trouble is, that you return from init. Normally, avoid return from an initializer if your initializer is not fail-able / init? /. In case of fail-able init? the only accepted return value is nil.

user3441734
  • 16,722
  • 2
  • 40
  • 59