'自'在所有成员初始化之前由关闭捕获

时间:2017-02-22 22:28:19

标签: swift

好吧,所以只是开始,继承我的代码:

import UIKit
import ForecastIO

class Weather {
    var temp: Float
    var condition: String
    var wind: Float
    var precip: Float

    init() {
        DarkSkyClient(apiKey: "<api key>").getForecast(latitude: Utils().getLat(), longitude: Utils().getLong()) { result in

            switch result {
            case .success(let currentForecast, _):

                self.temp = (currentForecast.currently?.temperature)!
                self.condition = (currentForecast.currently?.summary)!
                self.wind = (currentForecast.currently?.windSpeed)!
                self.precip = (currentForecast.currently?.precipitationProbability)!

            case .failure(let error):
                print(error)

            }

        }

    }

}

所以我的错误出现了,因为我试图在API调用中初始化temp。我知道这不是最可靠的做法,但我试图让它首先发挥作用。

第一个错误是:

  

&#39;自&#39;在所有成员初始化之前由关闭捕获

DarkSkyClient(apiKey: "").getForecast(latitude: Utils().getLat(), longitude: Utils().getLong()) { result in

我的第二个错误:

  

从初始化程序返回,而不初始化所有存储的属性

在倒数第二个}

现在,显然我没有正确初始化。我无法找到正确的方法来完成我的最终目标。也许我这样做完全错了?

3 个答案:

答案 0 :(得分:6)

您有两个选项,将属性声明为选项,或使用默认值初始化它们(这意味着它们将是非选项)

var temp: Float?
var condition: String?
var wind: Float?
var precip: Float?

var temp: Float=0
var condition: String=""
var wind: Float=0
var precip: Float=0

答案 1 :(得分:4)

我有可能猜到你遇到了并发问题。在异步调用DarkSkyClient之前,您可能正在尝试访问对象的属性(如果我错了,请提前道歉)。即,事件的顺序是......

  1. 天气对象已初始化,将temp设置为0
  2. 开始调用DarkSkyClient,在后台运行
  3. 读取临时变量 - 嘿,它是0!
  4. 调用DarkSkyClient完成后,将temp设置为您真正想要的值。坏
  5. 所以你真正需要做的是切换到控制模式的反转:

    class Weather {
        var temp: Float
        var condition: String
        var wind: Float
        var precip: Float
    
        init(forecast: Forecast) {
            temp = (forecast.currently?.temperature)!
            condition = (forecast.currently?.summary)!
            wind = (forecast.currently?.windSpeed)!
            precip = (forecast.currently?.precipitationProbability)!
        }
    
        static func getWeather() {
            DarkSkyClient(apiKey: "<api key>").getForecast(latitude: Utils().getLat(), longitude: Utils().getLong()) { result in
    
                switch result {
                case .success(let currentForecast, _):
                    let weather = Weather(forecast: currentForecast)
                    // Display the weather somewhere
                    doSomethingWith(weather: weather)
                case .failure(let error):
                    print(error)
                }
            }
        }    
    }
    

    如果您不熟悉使用异步API进行开发,那么阅读这个主题是值得的。它可能非常棘手(遗憾的是,我没有任何关于良好引物的建议)。 希望这有帮助!

答案 2 :(得分:1)

对我来说,这是因为我没有在初始化程序中调用super.init()

class AnObject: NSObject {
    override init() {
//        super.init()

        let _: ()-> (Void) = {
            print(String(describing: self))
        }
    }
}