Swift 5 : 转义闭包捕获 'inout' 参数
Swift 5 : Escaping closure captures 'inout' parameter
我已经有了从服务器收到的响应数据。此响应数据有一些面包师数据。
现在我想计算用户和面包店的距离,然后将其存储在相同的模态中class。我为它创建了一个函数。由于此功能需要在 4,5 视图控制器中使用,我的计划是创建为 UIViewController
的扩展
func getDistanceUserBakery(bakeryData : inout [BakeryRecord], completion : @escaping (Int?) -> () ) {
for index in 0...(bakeryData.count-1) {
//1
let googleApiAdd = "https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&"
//2
let origin = "origins=\(UserLocation.coordinates.latitude),\(UserLocation.coordinates.longitude)"
//3
let destination = "&destinations=\(bakeryData[index].location?.coordinates?[1] ?? 0.0),\(bakeryData[index].location?.coordinates?[0] ?? 0.0)"
//4
let googleKey = "&key=\(GOOGLE_KEY)"
//5
let url = googleApiAdd + origin + destination + googleKey
let request = URLRequest(url: URL(string: url)!)
//6 - this line is showing the error.
let task = URLSession.shared.dataTask(with: request) {(data, response, error) in
guard let data = data else {
completion(nil)
Toast.show(message: "Unable to calculate distance from user to bakery", controller: self)
return }
let stringResponse = String(data: data, encoding: .utf8)!
let dictData = stringResponse.convertToDictionary()
do {
let jsonData = try JSONSerialization.data(withJSONObject: dictData as Any, options: .prettyPrinted)
let decoder = JSONDecoder()
let model = try decoder.decode(GoogleDistance.self, from: jsonData)
bakeryData[index].disanceInMiles = model.rows?[0].elements?[0].distance?.text ?? "NaN"
completion(index)
} catch let parsingError {
print("Error data :", parsingError)
completion(nil)
}
}
task.resume()
}
这是我从服务器接收到数据后调用此函数的方式,
self.getDistanceUserBakery(bakeryData: &self.bakeryData) { index in
if index != nil {
DispatchQueue.main.async {
// here I am thinking as the bakeryData will hold the new value for distanceInMiles, the collectionView will start showing up that result on reload.
self.resultCollection.reloadItems(at: [IndexPath(item: index!, section: 0)])
}
}
}
现在问题:
据我所知,当您将参数作为 inout 传递时,可以从函数内部更改值,这些更改会反映在函数外部的原始值中。
但是当我尝试代码时,它说 Escaping closure captures 'inout' parameter 'bakeryData'。在我的代码中,//6 产生错误。
如何解决这个错误?
正如@Paulw11 在评论中建议的那样,
Is BakeryData a struct? If so then simply make it a class. If you make
BakerData a class then the array contains reference types and you can
update the element's properties
我将结构更改为 class,它确实有效。
我已经有了从服务器收到的响应数据。此响应数据有一些面包师数据。
现在我想计算用户和面包店的距离,然后将其存储在相同的模态中class。我为它创建了一个函数。由于此功能需要在 4,5 视图控制器中使用,我的计划是创建为 UIViewController
的扩展func getDistanceUserBakery(bakeryData : inout [BakeryRecord], completion : @escaping (Int?) -> () ) {
for index in 0...(bakeryData.count-1) {
//1
let googleApiAdd = "https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&"
//2
let origin = "origins=\(UserLocation.coordinates.latitude),\(UserLocation.coordinates.longitude)"
//3
let destination = "&destinations=\(bakeryData[index].location?.coordinates?[1] ?? 0.0),\(bakeryData[index].location?.coordinates?[0] ?? 0.0)"
//4
let googleKey = "&key=\(GOOGLE_KEY)"
//5
let url = googleApiAdd + origin + destination + googleKey
let request = URLRequest(url: URL(string: url)!)
//6 - this line is showing the error.
let task = URLSession.shared.dataTask(with: request) {(data, response, error) in
guard let data = data else {
completion(nil)
Toast.show(message: "Unable to calculate distance from user to bakery", controller: self)
return }
let stringResponse = String(data: data, encoding: .utf8)!
let dictData = stringResponse.convertToDictionary()
do {
let jsonData = try JSONSerialization.data(withJSONObject: dictData as Any, options: .prettyPrinted)
let decoder = JSONDecoder()
let model = try decoder.decode(GoogleDistance.self, from: jsonData)
bakeryData[index].disanceInMiles = model.rows?[0].elements?[0].distance?.text ?? "NaN"
completion(index)
} catch let parsingError {
print("Error data :", parsingError)
completion(nil)
}
}
task.resume()
}
这是我从服务器接收到数据后调用此函数的方式,
self.getDistanceUserBakery(bakeryData: &self.bakeryData) { index in
if index != nil {
DispatchQueue.main.async {
// here I am thinking as the bakeryData will hold the new value for distanceInMiles, the collectionView will start showing up that result on reload.
self.resultCollection.reloadItems(at: [IndexPath(item: index!, section: 0)])
}
}
}
现在问题:
据我所知,当您将参数作为 inout 传递时,可以从函数内部更改值,这些更改会反映在函数外部的原始值中。
但是当我尝试代码时,它说 Escaping closure captures 'inout' parameter 'bakeryData'。在我的代码中,//6 产生错误。
如何解决这个错误?
正如@Paulw11 在评论中建议的那样,
Is BakeryData a struct? If so then simply make it a class. If you make BakerData a class then the array contains reference types and you can update the element's properties
我将结构更改为 class,它确实有效。