Swift ||从 API 调用中返回可由其他方法使用的 class
Swift || Returning a class that can be used by other methods from an API call
我正在从移动应用程序调用 HERE Weather API,需要 return 当前天气作为对象,以便其他方法可以在给定时间段内使用该信息(例如 30 分钟更新间隔)。
我对基于此站点的异步调用有粗略的了解 https://fluffy.es/return-value-from-a-closure/ 但我仍然 运行 我无法访问我在关闭之外创建的 Weather 对象的问题完成处理程序。
我已经从天气 class 中提供了 Get 方法。我还在 AppDelegates 文件中提供了对该 Get 方法的调用。
public static func Get(lat:String, long:String, completionHandler: @escaping (Weather?) -> Void) {
//Keys go here
var request = URLRequest(
url: URL(string: "https://weather.cit.api.here.com/weather/1.0/report.json?app_code=-fJW5To2WdHdwQyYr_9ExQ&app_id=2m83HBDDcwAqTC2TqdLR&product=observation&latitude="+lat+"&longitude="+long+"&oneobservation=true")!)
request.httpMethod = "GET"
URLSession.shared.dataTask(with: request, completionHandler: { dat, response, error in
do {
guard let json = try? JSONSerialization.jsonObject(with: dat as! Data, options: []) else {throw JSONParseError.missingJSON}
//parse json for dictionaries
guard let response = json as? [String: Any] else {throw JSONParseError.responseNotADictionary}
guard let observations = response["observations"] as? [String: Any] else {throw JSONParseError.observationsNotADictionary}
guard let locationJSON = observations["location"] as? [Any] else {throw JSONParseError.locationNotAnArray}
guard let location = locationJSON.first as? [String: Any] else {throw JSONParseError.locationNotADictionary}
guard let observationJSON = location["observation"] as? [Any] else {throw JSONParseError.observationNotAnArray}
guard let observation = observationJSON.first as? [String: Any] else {throw JSONParseError.observationNotADictionary}
//search dictionaries for values
guard let feedCreation = response["feedCreation"] as? String else {throw JSONParseError.missingFeedCreationObject}
guard let city = location["city"] as? String else {throw JSONParseError.missingCityObject}
guard let state = location["state"] as? String else {throw JSONParseError.missingStateObject}
guard let temperature = observation["temperature"] as? String else {throw JSONParseError.missingTemperatureObject}
guard let icon = observation["icon"] as? String else {throw JSONParseError.missingIconObject}
guard let iconName = observation["iconName"] as? String else {throw JSONParseError.missingIconNameObject}
//create weather object and return
guard let currentWeather = Weather(feedCreation: feedCreation,state: state,city: city,temperature: temperature,icon: icon,iconName: iconName) else {throw WeatherObjectCreationError.objectCreationFailed}
completionHandler(currentWeather)
} catch {
print("JSON Serialization error")
}
}).resume()
}
Weather.Get(lat:"32.9005", long:"-96.7869", completionHandler: {currentWeather in
if let testWeather = currentWeather{
//Works fine
print(testWeather.city)
print("completionHandler")
}
})
//Error says testWeather is not intialized
print(testWeather.city)
在我的 Weather.Get 调用结束时,我应该能够从其他方法访问 testWeather 对象。具体来说,一种根据该地区当前天气修改限速的方法,由 Weather.Get 调用 returned。
您没有理解的是,您的 GET 调用中的完成处理程序与原始 Weather API 调用一样异步。因此,您不能 运行 任何代码 after 它取决于 in 它的内容。活动顺序如下:
// 1
Weather.Get(lat:"32.9005", long:"-96.7869", completionHandler: {currentWeather in
if let testWeather = currentWeather{ // 3!!!
print(testWeather.city) // 4!!!!!!
print("completionHandler")
}
})
print(testWeather.city) // 2
另外,最后一行的testWeather
是什么?是 属性、self.testWeather
吗?它需要是。但即使是,你也忽略了给 self.testWeather
赋值; if let testWeather
是一个 different testWeather
(它仅在完成处理程序中是本地的,不能 "leak" 超出它)。但是,即使您这样做了,它 still 也不会起作用,因为代码 still 运行 的顺序是错误的:
// 1
Weather.Get(lat:"32.9005", long:"-96.7869", completionHandler: {currentWeather in
if let testWeather = currentWeather{ // 3
print(testWeather.city) // 4
print("completionHandler")
self.testWeather = testWeather // 5; better but it won't help the _next_ print
}
})
print(testWeather.city) // 2
不过,记得写入 self.testWeather
(5) 至少会允许 other 代码访问此值,前提是 运行s 后来.
我正在从移动应用程序调用 HERE Weather API,需要 return 当前天气作为对象,以便其他方法可以在给定时间段内使用该信息(例如 30 分钟更新间隔)。
我对基于此站点的异步调用有粗略的了解 https://fluffy.es/return-value-from-a-closure/ 但我仍然 运行 我无法访问我在关闭之外创建的 Weather 对象的问题完成处理程序。
我已经从天气 class 中提供了 Get 方法。我还在 AppDelegates 文件中提供了对该 Get 方法的调用。
public static func Get(lat:String, long:String, completionHandler: @escaping (Weather?) -> Void) {
//Keys go here
var request = URLRequest(
url: URL(string: "https://weather.cit.api.here.com/weather/1.0/report.json?app_code=-fJW5To2WdHdwQyYr_9ExQ&app_id=2m83HBDDcwAqTC2TqdLR&product=observation&latitude="+lat+"&longitude="+long+"&oneobservation=true")!)
request.httpMethod = "GET"
URLSession.shared.dataTask(with: request, completionHandler: { dat, response, error in
do {
guard let json = try? JSONSerialization.jsonObject(with: dat as! Data, options: []) else {throw JSONParseError.missingJSON}
//parse json for dictionaries
guard let response = json as? [String: Any] else {throw JSONParseError.responseNotADictionary}
guard let observations = response["observations"] as? [String: Any] else {throw JSONParseError.observationsNotADictionary}
guard let locationJSON = observations["location"] as? [Any] else {throw JSONParseError.locationNotAnArray}
guard let location = locationJSON.first as? [String: Any] else {throw JSONParseError.locationNotADictionary}
guard let observationJSON = location["observation"] as? [Any] else {throw JSONParseError.observationNotAnArray}
guard let observation = observationJSON.first as? [String: Any] else {throw JSONParseError.observationNotADictionary}
//search dictionaries for values
guard let feedCreation = response["feedCreation"] as? String else {throw JSONParseError.missingFeedCreationObject}
guard let city = location["city"] as? String else {throw JSONParseError.missingCityObject}
guard let state = location["state"] as? String else {throw JSONParseError.missingStateObject}
guard let temperature = observation["temperature"] as? String else {throw JSONParseError.missingTemperatureObject}
guard let icon = observation["icon"] as? String else {throw JSONParseError.missingIconObject}
guard let iconName = observation["iconName"] as? String else {throw JSONParseError.missingIconNameObject}
//create weather object and return
guard let currentWeather = Weather(feedCreation: feedCreation,state: state,city: city,temperature: temperature,icon: icon,iconName: iconName) else {throw WeatherObjectCreationError.objectCreationFailed}
completionHandler(currentWeather)
} catch {
print("JSON Serialization error")
}
}).resume()
}
Weather.Get(lat:"32.9005", long:"-96.7869", completionHandler: {currentWeather in
if let testWeather = currentWeather{
//Works fine
print(testWeather.city)
print("completionHandler")
}
})
//Error says testWeather is not intialized
print(testWeather.city)
在我的 Weather.Get 调用结束时,我应该能够从其他方法访问 testWeather 对象。具体来说,一种根据该地区当前天气修改限速的方法,由 Weather.Get 调用 returned。
您没有理解的是,您的 GET 调用中的完成处理程序与原始 Weather API 调用一样异步。因此,您不能 运行 任何代码 after 它取决于 in 它的内容。活动顺序如下:
// 1
Weather.Get(lat:"32.9005", long:"-96.7869", completionHandler: {currentWeather in
if let testWeather = currentWeather{ // 3!!!
print(testWeather.city) // 4!!!!!!
print("completionHandler")
}
})
print(testWeather.city) // 2
另外,最后一行的testWeather
是什么?是 属性、self.testWeather
吗?它需要是。但即使是,你也忽略了给 self.testWeather
赋值; if let testWeather
是一个 different testWeather
(它仅在完成处理程序中是本地的,不能 "leak" 超出它)。但是,即使您这样做了,它 still 也不会起作用,因为代码 still 运行 的顺序是错误的:
// 1
Weather.Get(lat:"32.9005", long:"-96.7869", completionHandler: {currentWeather in
if let testWeather = currentWeather{ // 3
print(testWeather.city) // 4
print("completionHandler")
self.testWeather = testWeather // 5; better but it won't help the _next_ print
}
})
print(testWeather.city) // 2
不过,记得写入 self.testWeather
(5) 至少会允许 other 代码访问此值,前提是 运行s 后来.