假設我有一個顯示兩個數字的 SwiftUI 組件。下面的示例代碼模擬了一個簡單的情況,即隨機不時更新兩個數字。
struct ContentView: View {
@State var number1: Int = 0
@State var number2: Int = 0
var timer:Timer {
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
if (Int.random(in: 0...100)<10) {
print("random event happened, increase numbers!")
self.number1 = self.number1 1
self.number2 = self.number2 1
}
}
}
var body: some View {
ZStack {
SampleNumbersView(numbers1: number1, numbers2: number2)
}.onAppear {
let _ = self.timer
}
}
}
struct SampleNumbersView: View {
var numbers1:Int = 0
var numbers2:Int = 0
var body: some View {
VStack {
Text("Number 1: \(numbers1)")
Text("Number 2: \(numbers2)")
}
}
}
上面的代碼有效。但是,如果我希望在更新兩個數字時發生以下影片序列,該怎么辦?
- 先顯示更新后的數字1
- 1 秒后顯示更新的數字 2
- 1 秒后繼續使這兩個數字閃爍幾次。
理論上影片的功能大致是這樣的
func updateNumber1and2(number1: Int, number2:Int) {
//first show number1
self.number1 = number1
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false) { _ in
//next show number 2
self.number2 = number2
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false) { _ in
//next blink text twice
print("start blinking")
self.numbersBlinking = true
Timer.scheduledTimer(withTimeInterval: 0.2, repeats: false) { _ in
print("stop blinking")
self.numbersBlinking = false
}
}
}
}
但是我不知道何時或如何在 SwiftUI 組件中執行這樣的函式?
uj5u.com熱心網友回復:
SwiftUI 有一個內置的影片函式,它們是由變數的變化觸發的。你不必自己滾動。當然不是多個計時器。如果您要使用計時器,則可以使用一個計時器,并根據該計時器跟蹤事情何時發生變化。不建議使用多個定時器。
由于您列出的要求,此代碼比普通影片稍微復雜一些,但您需要延遲。如果你只是想讓視圖在變化中閃爍,我會簡單地包裹animator在withAnimation()塊中,它會在變化時立即閃爍。
struct AnimatedTextView: View {
@State var number1: Int = 0
@State var number2: Int = 0
@State var animator = false
var body: some View {
VStack {
Button { // Changed your timer to a button so that you don't have to wait for some random event
self.number1 = self.number1 1
// This delays the execution by 1 second.
DispatchQueue.main.asyncAfter(deadline: .now() 1) {
self.number2 = self.number2 1
}
// This delays the execution by 2 seconds.
DispatchQueue.main.asyncAfter(deadline: .now() 2) {
withAnimation(.easeInOut(duration: 0.2).repeatCount(10)) {
// Changing this to true causes the opacity of the view to go to 0.
// By putting it in an animated block, the change will be slowed and repeated 5 times
// On and off each separately count as a time
animator = true
}
// This delays the execution by 1 second after the animator variable is changed.
DispatchQueue.main.asyncAfter(deadline: .now() 1) {
// This gives time for the animation to complete and then sets the opacity back to 1
// Otherwise the view will be hidden. It is essentially a reset.
animator = false
}
}
} label: {
Text("Change Numbers")
}
SampleNumbersView(numbers1: number1, numbers2: number2)
// animator is used here to change the opacity, and it is animated repeatedly
// causing the view to blink.
.opacity(animator ? 0 : 1)
}
}
}
struct SampleNumbersView: View {
// Since you are not changing the numbers in this view, declare them as let
// and do not give them an initial value. There is less system overhead.
let numbers1: Int
let numbers2: Int
var body: some View {
VStack {
Text("Number 1: \(numbers1)")
Text("Number 2: \(numbers2)")
}
}
}
而且,為了回答您的原始問題,如果您使用的是 iOS 14 或更高版本,您將使用.onChange(of:perform:)其中一個視圖來捕獲更新并像這樣運行您的函式:
.onChange(of: number1) { _ in
updateNumber1and2(number1: number1, number2:number2)
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/339608.html
