gpt4 book ai didi

binding - SwiftUI:@Binding 值更改时收到通知

转载 作者:行者123 更新时间:2023-12-02 12:02:33 24 4
gpt4 key购买 nike

我编写了一个 View 来在 SwiftUI 中创建打字机效果 - 当我传入绑定(bind)变量时,它第一次工作正常,例如:TypewriterTextView($textString)

但是,textString 值随后发生任何更改都将不起作用(因为绑​​定值不会直接放置在正文中)。我对有关如何在 View 中更改 @Binding var 时手动收到通知的任何想法感兴趣。

struct TypewriterTextView: View {

@Binding var textString:String
@State private var typingInterval = 0.3
@State private var typedString = ""

var body: some View {
Text(typedString).onAppear() {
Timer.scheduledTimer(withTimeInterval: self.typingInterval, repeats: true, block: { timer in

if self.typedString.length < self.textString.length {
self.typedString = self.typedString + self.textString[self.typedString.length]
}
else { timer.invalidate() }
})
}
}
}

最佳答案

使用onChange modifier而不是 onAppear() 来监视 textString 绑定(bind)。

struct TypewriterTextView: View {
@Binding var textString:String
@State private var typingInterval = 0.3
@State private var typedString = ""

var body: some View {
Text(typedString).onChange(of: textString) {
typedString = ""
Timer.scheduledTimer(withTimeInterval: self.typingInterval, repeats: true, block: { timer in

if self.typedString.length < self.textString.length {
self.typedString = self.typedString + self.textString[self.typedString.length]
}
else { timer.invalidate() }
})
}
}
}
<小时/>

兼容性

onChange 修饰符是在 WWDC 2020 上引入的,仅在

  • macOS 11+
  • iOS 14+
  • tvOS 14+
  • watchOS 7+

如果您想在旧系统上使用此功能,您可以使用以下填充程序。它基本上是使用旧版 SwiftUI 重新实现的 onChange 方法:

import Combine
import SwiftUI

/// See `View.onChange(of: value, perform: action)` for more information
struct ChangeObserver<Base: View, Value: Equatable>: View {
let base: Base
let value: Value
let action: (Value)->Void

let model = Model()

var body: some View {
if model.update(value: value) {
DispatchQueue.main.async { self.action(self.value) }
}
return base
}

class Model {
private var savedValue: Value?
func update(value: Value) -> Bool {
guard value != savedValue else { return false }
savedValue = value
return true
}
}
}

extension View {
/// Adds a modifier for this view that fires an action when a specific value changes.
///
/// You can use `onChange` to trigger a side effect as the result of a value changing, such as an Environment key or a Binding.
///
/// `onChange` is called on the main thread. Avoid performing long-running tasks on the main thread. If you need to perform a long-running task in response to value changing, you should dispatch to a background queue.
///
/// The new value is passed into the closure. The previous value may be captured by the closure to compare it to the new value. For example, in the following code example, PlayerView passes both the old and new values to the model.
///
/// ```
/// struct PlayerView : View {
/// var episode: Episode
/// @State private var playState: PlayState
///
/// var body: some View {
/// VStack {
/// Text(episode.title)
/// Text(episode.showTitle)
/// PlayButton(playState: $playState)
/// }
/// }
/// .onChange(of: playState) { [playState] newState in
/// model.playStateDidChange(from: playState, to: newState)
/// }
/// }
/// ```
///
/// - Parameters:
/// - value: The value to check against when determining whether to run the closure.
/// - action: A closure to run when the value changes.
/// - newValue: The new value that failed the comparison check.
/// - Returns: A modified version of this view
func onChange<Value: Equatable>(of value: Value, perform action: @escaping (_ newValue: Value)->Void) -> ChangeObserver<Self, Value> {
ChangeObserver(base: self, value: value, action: action)
}
}

关于binding - SwiftUI:@Binding 值更改时收到通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58363563/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com