Ios Swift:如何从异步操作返回值?
我正在使用SwiftyVK和SwiftyJSON框架创建一个社交网络应用程序。有一个功能,它发送一个附带照片的帖子。让我们称之为sendToVK()。以下是对它的简要回顾:Ios Swift:如何从异步操作返回值?,ios,multithreading,swift3,vk,Ios,Multithreading,Swift3,Vk,我正在使用SwiftyVK和SwiftyJSON框架创建一个社交网络应用程序。有一个功能,它发送一个附带照片的帖子。让我们称之为sendToVK()。以下是对它的简要回顾: func sendToVK(message: String, photos: [UIImage]) { // declaration of some vars and lets var attachments = "" // this var should collect all the informatio
func sendToVK(message: String, photos: [UIImage]) {
// declaration of some vars and lets
var attachments = "" // this var should collect all the information about
//photos to attach, for example: "photo123456_987654,photo123456_612366,photo123456_123156",
// where 123456 is id of the user, whose wall I'm going post to (I already have it),
// numbers after "_" are id of the photo, they are contained in the server's response
// in case of successful upload
for photo in photos {
// I'm uploading photos in this loop, and I assume that I have to get
//the ID's of my photos from server's response also somewhere in this loop in order to work with them further
//Let's say photoString is someString + photoID, for example, photoString == "photo12345_9876543"
var photoID = ""
//the following function is uploading photos asynchronously.
//It is also responsible for getting IDs from server's response
VK.API.Upload.Photo.toWall.toUser(media, userId: userIDForVK).send(
onSuccess: { response in
print("\n SwiftyVK: uploadPhoto success \n \(response)")
photoID = response[0,"id"].stringValue }, //this is SwiftyJSON syntax
onError: { error in
print("\n SwiftyVK: uploadPhoto fail \n \(error)") },
onProgress: { done, total in
print("\n SwiftyVK: uploadPhoto progress: \(done) of \(total))") }
)
photoString = something + photoID //by this moment photoID is empty, that's the problem! (see explanation below)
attachments += photoString
}
//At this moment I must have all the neccessary parameters
//in the var wallPostParameters, including attachments!
VK.API.Wall.post(wallPostParameters).send(
onSuccess: {response in print(response)},
onError: {error in print(error)},
onProgress: {done, total in print(" !!!!!!!!!!!!!!! send \(done) of \(total)")}
)
}
因此,确切的问题是,在循环内部,上载任务被分派到另一个线程,服务器的响应在另一个时间分别到达其他地方。事实上,当我需要我的附件字符串填充photoStrings时(就在调用VK.API.Wall.post()之前),它实际上有一个表单,例如,“photo123456,photo123456,photo123456”,即没有照片ID,因为这些照片还没有上传到另一个线程中,因此,这些ID没有添加到附件中
问题是,我如何在Swift中实现,在循环的每个迭代中,我们不继续,而是等待照片上传,将其id添加到photoString以收集附件中的photoString,所以在调用VK.API.Wall.post()之前一切都准备好了吗?像这样的东西在你的情况下会有用的
func sendToVK(message: String, photos: [UIImage]) {
var attachments = ""
var photosUploaded = 0
for photo in photos {
var photoID = ""
VK.API.Upload.Photo.toWall.toUser(media, userId: userIDForVK).send(
onSuccess: { response in
photosUploaded += 1
photoID = response[0,"id"].stringValue
photoString = something + photoID
attachments += photoString
if photosUploaded == photos.count {
VK.API.Wall.post(wallPostParameters).send(
onSuccess: {response in print(response)},
onError: {error in print(error)},
onProgress: {done, total in print(" !!!!!!!!!!!!!!! send \(done) of \(total)")}
)
}
}, //this is SwiftyJSON syntax
onError: { error in
print("\n SwiftyVK: uploadPhoto fail \n \(error)") },
onProgress: { done, total in
print("\n SwiftyVK: uploadPhoto progress: \(done) of \(total))") }
)
}
}
我在Swift上读过一篇关于GCD的文章,我的最终解决方案是:
private static func sendToVK(_ message: String, photos: [UIImage], userIDForVK: String) {
var wallPostParameters = Dictionary<VK.Arg, String>()
wallPostParameters[VK.Arg.message] = message
var attachments = ""
var successfulUploadsCount = 0
let sendPostWorkItem = DispatchWorkItem {
VK.API.Wall.post(wallPostParameters).send(
onSuccess: {response in print(response)},
onError: {error in print(error)},
onProgress: {done, total in print("\n send \(done) of \(total)\n")} )
}
for photo in photos {
let media = Media(imageData: Data(UIImageJPEGRepresentation(photo, 1.0)!), type: Media.ImageType.JPG)
VK.API.Upload.Photo.toWall.toUser(media, userId: userIDForVK).send(
onSuccess: { response in
let photoID = response[0,"id"].stringValue
let photoString = "photo" + userIDForVK + "_" + photoID
if attachments.isEmpty {
attachments = photoString
} else {
attachments += "," + photoString
}
successfulUploadsCount += 1
if successfulUploadsCount == photos.count {
wallPostParameters[VK.Arg.attachments] = attachments
sendPostWorkItem.perform()
}
print("\n SwiftyVK: uploadPhoto success \n \(response)\n") },
onError: { error in
print("\n SwiftyVK: uploadPhoto fail \n \(error)\n") },
onProgress: { done, total in
print("\n SwiftyVK: uploadPhoto progress: \(done) of \(total))\n") } )
}
if photos.isEmpty {
sendPostWorkItem.perform()
}
}
private static func sendToVK(umessage:String,photos:[UIImage],userIDForVK:String){
var wallPostParameters=字典()
wallPostParameters[VK.Arg.message]=消息
var attachments=“”
var successfulluploadsCount=0
让sendPostWorkItem=DispatchWorkItem{
VK.API.Wall.post(wallPostParameters.send)(
onSuccess:{打印响应(响应)},
OneError:{打印错误(错误)},
onProgress:{完成,打印总数(“\n发送\(完成)\(总计)\n”)})
}
对于照片中的照片{
让媒体=媒体(imageData:Data(UIImageJPEGresentation(photo,1.0)!),类型:media.ImageType.JPG)
API.Upload.Photo.toWall.toUser(媒体,用户名:userIDForVK).send(
onSuccess:{中的响应
让photoID=response[0,“id”].stringValue
让photoString=“photo”+userIDForVK+“\u”+photoID
如果附件是空的{
附件=photoString
}否则{
附件+=”,“+photoString
}
成功上载NT+=1
如果成功上载,则NT==photos.count{
wallPostParameters[VK.Arg.attachments]=附件
sendPostWorkItem.perform()
}
打印(“\n SwiftyVK:uploadPhoto success\n\(response)\n”),
onError:{中有错误
打印(“\n SwiftyVK:uploadPhoto失败\n\(错误)\n”),
onProgress:{已完成,总计
打印(“\n SwiftyVK:uploadPhoto progress:\(完成)共\(总计))\n”)})
}
如果照片是空的{
sendPostWorkItem.perform()
}
}
如果你有要上传的照片数量,只需在循环之外再做一个变量,在每次成功时+1,并将其与要上传的照片数量进行比较,然后只执行代码,代码也应该放在闭包调用中back@Tj3n我怎样才能防止以下代码在Swift中执行?下面的答案看起来不错:D