ios - Alamofire doesn't execute whole code in response closure
问题描述
I'm trying to get photos of user. On the TableView of friends list I call the function
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard segue.identifier == "showFriendSegue" else {return}
guard let showFriend = segue.destination as? FriendCollectionViewController else {return}
let indexPath = self.tableView.indexPathForSelectedRow
let userKey = usersSectionTitles[indexPath!.section]
if let userValues = usersDictionary[userKey] {
let user = userValues[indexPath!.row]
let id = userValues[indexPath!.row].id
showFriend.friend.append(user)
showFriend.friendImages = Photo.photo.getUserPhotos(id: id)
}
}
func getUserPhotos(id: Int) -> [String]{
let url = URL(string: "https://api.vk.com/method/photos.get")!
let parameters: Parameters = [
"owner_id" : id,
"album_id" : "profile",
"rev" : 1,
"access_token" : Session.session.token,
"v": Session.session.APIVersion
]
var userPhotos: [String] = []
AF.request(url, method: .get, parameters: parameters, headers: nil).responseJSON { (response) in
switch response.result {
case .success(let value):
let json = JSON(value)
let photosArray = json["response"]["items"].arrayValue
for sizes in photosArray {
let onlyOneType = sizes["sizes"].arrayValue.filter({$0["type"] == "z"})
for url in onlyOneType {
userPhotos.append(url["url"].stringValue)
}
}
case .failure(let error):
print(error)
}
}
return userPhotos
}
It seems for me like Alamofire doesn't have enough time to make whole code and it's strange because I expect that code should be executed consistently. When I check code with breakpoints I see that AF.request starts, then right away return userPhotos executes, photosArray is not empty but on the friend's page I have an empty array of photos. How should I fill the array from AF? I thought it was obvious and simple thing but I can't understand what's wrong with this closure.
解决方案
Alamofire request runs asynchronously, that's why your code returns empty userPhotos
at once. You need to use completion handler for this function. It will be called when your request returns a response with ids.
And I recommend to call this function in the FriendCollectionViewController
instead of func prepare(for segue: UIStoryboardSegue, sender: Any?)
.
Attach code snippet below how to use completion for your case.
func getUserPhotos(id: Int, completion: @escaping (Result<[String], Error>) -> Void) {
let url = URL(string: "https://api.vk.com/method/photos.get")!
let parameters: Parameters = [
"owner_id" : id,
"album_id" : "profile",
"rev" : 1,
"access_token" : Session.session.token,
"v": Session.session.APIVersion
]
AF.request(url, method: .get, parameters: parameters, headers: nil).responseJSON { (response) in
switch response.result {
case .success(let value):
let json = JSON(value)
let photosArray = json["response"]["items"].arrayValue
var userPhotos: [String] = []
for sizes in photosArray {
let onlyOneType = sizes["sizes"].arrayValue.filter({$0["type"] == "z"})
for url in onlyOneType {
userPhotos.append(url["url"].stringValue)
}
}
completion(.success(userPhotos))
case .failure(let error):
print(error)
completion(.failure(error))
}
}
}
Then you can call your method.
Photo.photo.getUserPhotos(id: friend[0].id, completion: { result in
switch result {
case .success(let ids):
// handle your ids here
case .failure:(let error):
// handle error
}
})
推荐阅读
- python-3.x - Pygame:用颜色填充文本的透明区域
- php - 将带有名字和姓氏的mysql字段拆分为2个php echo
- javascript - toastr javascript语法错误
- xcode - XCode 和 RubyMotion - rake 规范 - 权限错误
- c# - 单击母版页上的按钮时,Response.Redirect 不起作用
- java - 位图图像从库中选择未在 android 版本 5.0.2 的 imageview 中显示
- python - 使用 Python 将系统 verilog 打包数组转换为解包数组语法
- generics - 在没有 reified 关键字的 Kotlin 中获取泛型类型参数的运行时类
- newline - 新行在 PHP 5.6 中不起作用
- load-balancing - 负载均衡器是否需要负载均衡器?