在异步等待调用之后更新UI。

11

我从API加载书籍,在加载期间显示活动指示器,在服务器响应后更新标签。

activityView.isHidden = false
        
let task = detach {
    do {
        let books = try await self.bookService.fetchBooks()
        DispatchQueue.main.async {
            self.show(books: books)
        }
    } catch {
        DispatchQueue.main.async {
            self.resultLabel.text = error.localizedDescription
        }
    }
    DispatchQueue.main.async {
       self.activityView.isHidden = true
    }
}

//...

我的问题是,在主队列上更新UI的更好方法是什么?使用DispatchQueue.main.async看起来很丑陋,我猜还有更好的方法可以实现同样的功能。
我必须使用它,因为所有UI更新都应该在主线程上进行,而没有DispatchQueue.main.async会导致编译错误,例如:
“文本”属性隔离到全局演员“MainActor”,不能从非隔离上下文进行变异
或者
“isHidden”属性隔离到全局演员“MainActor”,不能从非隔离上下文进行变异
附:使用Xcode 13.0b2

MainActor.run - idmean
1个回答

11

像这样使用@MainActor -

self.updateAcitivityIndicator(isHidden: false)
        
let task = detach {
    do {
        let books = try await self.bookService.fetchBooks()
        self.showBooks(books)
    } catch {
        self.showError(error)
    }
    self.updateAcitivityIndicator(isHidden: true)
}

@MainActor
private func showBooks(_ books: [Book]) {
}

@MainActor
private func showError(_ error: Error) {
    self.resultLabel.text = error.localizedDescription
}

@MainActor
private func updateAcitivityIndicator(isHidden: Bool) {
    self.activityView.isHidden = isHidden
}

1
嘿,Tarun,什么是@MainActor?我不了解它,请告诉我。 - jatin fl
1
@jatinfl 请查看MainActor - 一个单例 actor,其执行器等同于主调度队列。 - Tarun Tyagi
1
所以,当使用@MainActor时,我们不需要操作GCDOperationQueue,对吧? - jatin fl
2
@jatinfl 这些是不同的概念,@MainActor 是为了解决 OP 需要解决的问题而引入的 async / await。请观看与 Swift 并发相关的 WWDC 2021 会议,您将知道您需要什么。 - Tarun Tyagi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接