我有一个使用合并和计时器的ViewModel,我希望这个ViewModel用一个新的动画更新LottieView和文件名。当计时器倒计时时,我希望它发布并发送特定的字符串,这些字符串将是json Lottie文件名。当我的ContentView收到这些文件名时,我希望它动态更新LottieViews动画。
因此,我在ContentView中创建了一个名为name的@State变量,并使其等于传入的接收值。但是,令我困惑的是,ViewModels计时器在10秒标记处发布和发送的文件名应该在LottieView中接收和使用(文件名:名称)。
然而,当我启动应用程序时,LottieView会立即运行该文件。为什么会这样?整个应用程序中唯一存在该文件名的地方是当计时器达到10秒时,它甚至不应该存在(name)。它也会忽略之前应该在19秒时执行的文件名称。如果我忽略LottieView(name)全部放在一起,并运行一个文本视图代替,所以在这种情况下文本(name),当我运行应用程序时,文本在计时器达到10时正确更改。
那么LottieView(Name)怎么会这样运行呢?我验证了这些文件也与它们的动画正确匹配。
import SwiftUI
import Combine
class ViewModel: ObservableObject {
var anyCancellable: AnyCancellable?
let publish = PassthroughSubject<String, Never>()
private var timer: Timer?
private var scheduleTime = 20
init() {
fire()
anyCancellable = publish.sink { str in
print("Value that is being passed over: \(str)")
}
}
func fire() {
print("Fire timer")
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
self.scheduleTime -= 1
print(self.scheduleTime)
if self.scheduleTime == 19 {
self.publish.send("13865-sign-for-error-flat-style")
}
if self.scheduleTime == 10 {
self.publish.send("4174-unlock-to-premium")
timer.invalidate()
}
}
}
}
import SwiftUI
import Combine
struct ContentView: View {
@ObservedObject var vm = ViewModel()
@State var name: String = ""
var body: some View {
VStack {
LottieView(filename: $name)
Text(name)
}
.onReceive(vm.publish, perform: { value in
print("passed over : \(value)")
name = value
print(name)
})
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
import SwiftUI
import Lottie
struct LottieView: UIViewRepresentable {
typealias UIViewType = UIView
@Binding var filename: String
func makeUIView(context: UIViewRepresentableContext<LottieView>) -> UIView {
let view = UIView(frame: .zero)
let animationView = AnimationView()
let animation = Animation.named(filename)
animationView.animation = animation
animationView.contentMode = .scaleAspectFit
animationView.play()
animationView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(animationView)
NSLayoutConstraint.activate([
animationView.widthAnchor.constraint(equalTo: view.widthAnchor),
animationView.heightAnchor.constraint(equalTo: view.heightAnchor),
animationView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
animationView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
return view
}
func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<LottieView>) {
}
}
1条答案
按热度按时间uqjltbpv1#
经过一天的搜索,没有找到一个答案,我可能想出了一个不是很正确的解决方案,但它似乎工作(保存临时fileName和更新LottieView后检查名称):