如何在多个闭包中更改变量并使用结果



我正在将 3 个不同的文件上传到 AWS S3 存储桶。我正在通过返回布尔值来检查每次上传是否成功。如果所有 3 次上传都成功,那么我代码的另一部分将运行。

我遇到的问题是 uploadSuccess var 正在闭包中更改,因此我的其余代码在更新之前正在运行。

我的代码如下:

上传功能-

func uploadData(fileUrl: URL, key: String, content: String, completion: @escaping(Bool) -> ()) {
var success = false
let expression = AWSS3TransferUtilityUploadExpression()
expression.progressBlock = {(task, progress) in
DispatchQueue.main.async(execute: {
// Do something e.g. Update a progress bar.
})
}
let transferUtility = AWSS3TransferUtility.default()
transferUtility.uploadFile(fileUrl, bucket: "liopa-datacapture-ios", key: key, contentType: content, expression: expression) { (task, error) in
if let error = error {
print("Error: (error.localizedDescription)")
success = false
completion(success)
return
}
print("Successfully uploaded")
success = true
completion(success)   
}
}

要上传的文件-

var videoSuccessful = false
var audioSuccessful = false 
var landmarksSuccessful = false 

// upload files to S3 bucket
// video file
s3Bucket.uploadData(fileUrl: videoRecorder.outputFileLocation!, key: "ios-videos/(userName)-(device)/session-(sessionNumber)-(sessionTimestamp)/video-(phraseNumber)/video-(phraseNumber).mp4", content: "video") { (success) in
DispatchQueue.main.async {
videoSuccessful = success
}
}
// audio file
s3Bucket.uploadData(fileUrl: audioRecorder.outputAudioLocation, key: "ios-videos/(userName)-(device)/session-(sessionNumber)-(sessionTimestamp)/video-(phraseNumber)/audio-(phraseNumber).flac", content: "audio") { (success) in
DispatchQueue.main.async {
audioSuccessful = success
}
}
//facial landmark coordinates
s3Bucket.uploadData(fileUrl: createFacialLandmarksFile(), key: "ios-videos/(userName)-(device)/session-(sessionNumber)-(sessionTimestamp)/video-(phraseNumber)/metadata/Phrase(phraseNumber)-landmarks.txt", content: "text") { (success) in
DispatchQueue.main.async {
landmarksSuccessful = success
}
}
print(uploadSuccessful)
if videoSuccessful && audioSuccessful && landmarksSuccessful  { // continue on

我知道我可能完全错误地这样做。但是我怎样才能立即更改 uploadSuccess Bool,然后在代码末尾的 if 语句中使用它的值呢?

你错过了几点:

您的上传是异步的。这意味着您应该在uploadSuccessful = success之前到达print(uploadSuccessful)
若要等待所有异步调用结束再执行其他操作,请使用DispatchGroup
即使这样,您也可能遇到问题,因为如果两个失败但不是最后一个,您将uploadSuccessful == true
您可以使用let allRequestSucceed = true在每个请求的关闭中,仅当success == false更新allRequestSucceed,但计数器也是一种好方法。

let group = DispatchGroup()
let successFullRequestCounter: Int = 0
//First upload
group.enter()
s3Bucket.uploadData(fileUrl: ...) { (success) in
if success { 
successFullRequestCounter = successFullRequestCounter + 1
}
group.leave()
}
//Second upload
group.enter()
s3Bucket.uploadData(fileUrl: ...) { (success) in
if success { 
successFullRequestCounter = successFullRequestCounter + 1
}
group.leave()
}
//Third upload
group.enter()
s3Bucket.uploadData(fileUrl: ...) { (success) in
if success { 
successFullRequestCounter = successFullRequestCounter + 1
}
group.leave()
}
//Because of the enter()/leave(), this code will executes only when 3 uploaded ended
group.notify(queue: DispatchQueue.main) {
if successFullRequestCounter == 3 { 
//All request did succeed
}
successFullRequestCounter = 0 //Reset the value if it's a instance var
}

最新更新