SwiftUI + Combine:如何将数据分配给带有动画的模型
Posted
技术标签:
【中文标题】SwiftUI + Combine:如何将数据分配给带有动画的模型【英文标题】:SwiftUI + Combine: how to assign data to a model with animation 【发布时间】:2021-07-28 12:24:25 【问题描述】:我正在使用Combine
来获取用户在搜索字段中键入的匹配项。它在去抖动、去重和获取数据方面效果很好。但我无法为项目的条目设置动画。当匹配到达时,ObservedObject
会立即更新,并且 UI 已经显示匹配。我更愿意为匹配项设置动画。
我认为问题在于匹配是在assign
方法中设置的,缺少withAnimation
。是否有可能以某种方式在Combine
管道中添加动画?我应该为此使用副作用吗?
代码如下:
class DictionarySearchViewModel: ObservableObject
@Published var translationMatches = [TranslationMatch]()
@Published var text: String = ""
@Published var isLoading = true
@Published var connectionError = false
private var cancellable: AnyCancellable? = nil
init()
cancellable = $text
.debounce(for: .seconds(0.1), scheduler: DispatchQueue.main)
.removeDuplicates()
.map [self] queryText -> AnyPublisher<[TranslationMatch], Never> in
if queryText.count < 2
return Future<[TranslationMatch], Never> promise in
promise(.success([TranslationMatch]()))
.eraseToAnyPublisher()
else
return DictionaryService.sharedInstance()
.searchMatchesPublisher(queryText)
.retry(3)
.replaceError(with: [TranslationMatch]())
.eraseToAnyPublisher()
else
return Future<[TranslationMatch], Never> promise in
promise(.success([TranslationMatch]()))
.eraseToAnyPublisher()
.switchToLatest()
.eraseToAnyPublisher()
.receive(on: DispatchQueue.main)
.assign(to: \.translationMatches, on: self)
struct DictionarySearchView: View
@ObservedObject var viewModel: DictionarySearchViewModel
var body: some View
ScrollView(.vertical, showsIndicators: false)
VStack(alignment: .leading, spacing: 15)
ForEach(viewModel.translationMatches, id: \.id) translationMatch in
Text(translationMatch.label)
【问题讨论】:
不要使用.assign(to: \.translationMatches, on: self)
- 它会创建对self
的强引用 - 改为使用assign(to:)
。但是如果仍然不能使用动画,那么你可以使用sink
来代替
【参考方案1】:
在ForEach
中的Text
上使用.animation
和.transition
。
Text(translationMatch.label)
.animation(.default)
.transition(AnyTransition.move(edge: .top))
https://developer.apple.com/tutorials/swiftui/animating-views-and-transitions
【讨论】:
你基本上是对的,但是动画修饰符应该在你指定一个过渡之后指定。在您上面编写的代码中,它将执行一个没有过渡的默认动画。以上是关于SwiftUI + Combine:如何将数据分配给带有动画的模型的主要内容,如果未能解决你的问题,请参考以下文章
使用 Combine 和 SwiftUI 在 Realm 中观察收集结果
如何使用 Combine 框架和 SwiftUI 发布网络请求的数据
如何使用 SwiftUI 和 Combine 检测 Datepicker 的值变化?
使用 SwiftUI、Combine 和 Firebase,我如何在将用户的帐户链接到电子邮件/密码之前验证用户是不是已匿名登录?