在視圖控制器中,用戶可以選擇影像,然后應用程式將上傳到服務器。
用戶可以一次選擇多張影像,也可以選擇多次。
每張上傳的圖片都會回傳一個 URL 供以后下載。
有一個提交按鈕可以將上傳影像的其他資訊和 URL 保存到服務器。
我希望當用戶按下提交按鈕時,應用程式將等待所有上傳的影像(回傳 URL 或引發錯誤)。
每次用戶選擇影像時,我都使用 await Taskgroup 并行上傳影像。
除了使用 sleep() 之外,還有什么方法可以等待上傳任務完成?
更新:
我上傳圖片的代碼:
let urls = try await upload(images: images, urls: urls)
func upload(images: [UIImage], urls: [String]) async throws -> [String] {
try await withThrowingTaskGroup(of: String.self, returning: [String].self) { group in
for (index, image) in images.enumerated() {
group.addTask { [self] in
guard let url = try? await upload(image: image, to: urls[index]) else {
return ""
}
return url
}
}
var downloadURLs = [String]()
for try await result in group {
if result != "" {
downloadURLs.append(result)
}
}
return downloadURLs
}
}
上傳圖片和提交資料是兩個不同的動作:
- 用戶選擇影像,之后該應用程式將自動上傳它們。
- 用戶可以隨時點擊提交按鈕,即使在上傳影像時,應用程式也必須等待上傳任務完成才能提交其他資料。
uj5u.com熱心網友回復:
如何[URL: UIImage]在您的班級中創建一個字典以保持上傳狀態(因此在開始/完成每個時添加/洗掉)并僅在該按鈕為空時啟用您的提交按鈕?請注意將其包裝到具有執行緒安全實作的類中。
編輯:如果無法禁用該按鈕,您可以執行以下操作:
import SwiftUI
import Combine
struct ContentView: View {
let viewModel = ViewModel()
var body: some View {
VStack {
Button {
self.viewModel.upload(url: URL(string: "https://google.com?id=\(UUID().uuidString)")!, image: UIImage())
self.viewModel.upload(url: URL(string: "https://google.com?id=\(UUID().uuidString)")!, image: UIImage())
}
label: {
Rectangle()
.fill(Color.red)
}
Button {
self.viewModel.submit()
}
label: {
Rectangle()
.fill(Color.blue)
}
}
.padding()
}
}
class ViewModel: ObservableObject {
var uploadRequests = [URL: UIImage]()
var submitting = false
let requestPublisher = PassthroughSubject<Bool, Never>()
var cancellable: AnyCancellable?
init() {
self.cancellable = requestPublisher.filter { [weak self] _ in
self?.submitting ?? false
}.sink { [weak self] _ in
self?.uploadToServer()
}
}
func upload(url: URL, image: UIImage) {
Task {
print("Uploading image")
self.uploadRequests[url] = image
try await Task.sleep(nanoseconds: 1_000_000_000)
self.uploadRequests[url] = nil
print("Image uploaded")
// If submit button was pressed meanwhile...
if self.uploadRequests.count == 0 {
self.requestPublisher.send(true)
}
}
}
func submit() {
self.submitting = true
guard self.uploadRequests.count == 0 else {
print("Still ongoing requests")
return
}
self.uploadToServer()
}
func uploadToServer() {
Task { [weak self] in
guard let self = self else { return }
print("Uploading to server")
self.submitting = false
}
}
}
uj5u.com熱心網友回復:
我假設你的上傳圖片功能看起來像這樣
func uploadImage(image: UIImage) async -> URL {
// some logic
}
并且您想讓許多上傳影像任務并行運行并等待所有上傳任務完成。所以我認為你可以做類似的事情
Task {
submitButton.isEnable = false
async let firstImage = uploadImage(image: image1)
async let secondImage = uploadImage(image: image2)
async let thirdImage = uploadImage(image: image3)
let images = await [firstImage, secondImage, thirdImage]
submitButton.isEnable = true
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/513490.html
標籤:迅速异步异步等待
