我构建了一个使用openweathermap API的天气应用程序。
它非常简单,应用程序使用plist文件存储城市列表。当用户启动应用程序时,它将遍历cityNames
数组,并检索所请求的天气数据。
我的问题是,应用会在发布时随机崩溃。它给出了#34;致命错误:在打开一个Optional值时意外地发现了nil。"在这行代码中,
let weather = Weather(labelCityName: cityName!, temp: temp!, icon: weatherIcon!)
如果每次都发生这种情况,我知道上述变量中有nil
。但问题是,使用相同的cityNames
列表,而不更改任何内容,我只需点击“运行”即可。然后'停止'然后'运行'再次在Xcode上。该应用可能会崩溃。
以下是我保存和加载plist文件的方法:
// Save city list
func documentsDirectory() -> String {
let path = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as [String]
return path[0]
}
func dataFilePath() -> String {
return "\(documentsDirectory())/Checklists.plist"
}
func saveCityList() {
let data = NSMutableData()
let archiver = NSKeyedArchiver(forWritingWithMutableData: data)
archiver.encodeObject(cityNames, forKey: "cityNames")
archiver.finishEncoding()
data.writeToFile(dataFilePath(), atomically: true)
}
// Load city list
func loadCityList() {
let path = dataFilePath()
if NSFileManager.defaultManager().fileExistsAtPath(path) {
if let data = NSData(contentsOfFile: path) {
let unarchiver = NSKeyedUnarchiver(forReadingWithData: data)
storedCityNames = unarchiver.decodeObjectForKey("cityNames") as! [String]
unarchiver.finishDecoding()
}
}
}
更新
我使用print
命令打印出每个数组cityNames
,temp
,weatherIcon
。这是当它在一些城市循环然后崩溃时的样子:
***Check***Optional("Albany"),Optional(272),Optional("04n")
***Check***nil,nil,nil
fatal error: unexpectedly found nil while unwrapping an Optional value
以下是使用SwiftyJSON获取数据的方法:
func getWeather(city: String) {
let cityEscaped = city.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())
let path = "http://api.openweathermap.org/data/2.5/weather?q=\(cityEscaped!)&appid=d21991d7851f849bfe8cc24d12c795d0"
let url = NSURL(string: path)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url!) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
let json = JSON(data: data!)
let temp = json["main"]["temp"].int
let weatherIcon = json["weather"][0]["icon"].string
let cityName = json["name"].string
print("***Check***\(cityName),\(temp),\(weatherIcon)")
let weather = Weather(labelCityName: cityName!, temp: temp!, icon: weatherIcon!)
if self.wServiceDelegate != nil {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.wServiceDelegate?.setWeather(weather)
})
}
}
task.resume()
}