Оператор Swift 2.0 Guard терпит неудачу при инициализации структуры

Была тема с таким же названием, но пример был ошибкой из-за ошибки пользователя. Я считаю, что этот пример является реальной проблемой XCode.

Я следовал учебнику по дому на дереве и в духе swift 2.0 использовал операторы защиты вместо того, чтобы вводить инициализатор. Мой код был идентичен инструкции, за исключением использования операторов защиты. У него была одна ошибка, в которой говорилось «возврат из инициализатора без инициализации всех сохраненных свойств». Как только я изменил его на операторы if let, это сработало. Возможно, я где-то ошибся, но я смотрел на это не менее часа, ни одно свойство не осталось неинициализированным.

Я сделал свойства равными nil в предложениях else на всякий случай, но это ни на что не повлияло.

структура 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)

  }
}

person R.P. Carson    schedule 14.02.2016    source источник
comment
добавьте точку останова к вашему инициализатору, затем повторно запустите свою программу... Пройдитесь по своему приложению, пока ваш инициализатор не вернется раньше, тогда у вас возникнет проблема.   -  person Dan Beaulieu    schedule 14.02.2016
comment
Кроме того, неудачный оператор защиты приводит к досрочному возврату, что в данном случае приводит к неудачной инициализации. If-let может быть лучшим выбором в этой ситуации, так как лучше иметь пустую метку, чем неудачную инициализацию.   -  person Dan Beaulieu    schedule 14.02.2016
comment
@DanBeaulieu ах, раннее возвращение, я думаю, вот оно что, спасибо. может быть, они добавят лучшее сообщение об ошибке в будущем? или это сработало бы, если бы я сделал неудачную инициализацию?   -  person R.P. Carson    schedule 14.02.2016
comment
Как насчет неудачного инициализатора (init?) developer.apple. com/library/mac/documentation/Swift/Conceptual/   -  person FranMowinckel    schedule 15.02.2016


Ответы (1)


Давайте

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

поскольку var i: Int? имеет значение по умолчанию nil, хотя i = 0 недоступен, если параметр init равен true, компилятор не жалуется.

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

НЕ будет компилироваться с error: return from initializer without initializing all stored properties и note: 'self.i' not initialized, потому что константа let i: Int? не имеет значения по умолчанию

Ваша беда в том, что вы возвращаетесь из init. Обычно избегайте возврата из инициализатора, если ваш инициализатор не имеет отказоустойчивости / init? /. В случае неудачной инициализации? единственно допустимое возвращаемое значение равно нулю.

person user3441734    schedule 14.02.2016