xcode 如何在swiftUI中触发x秒后的操作

zdwk9cvp  于 2023-03-13  发布在  Swift
关注(0)|答案(4)|浏览(128)

我一直在努力完成两个让我头疼的主要目标。如果这是一个简单的解决方案,我很抱歉,我对swift/swiftui还是有点陌生
1.在经过特定时间之后触发动作。
1.触发@State以基于经过的时间改变值。
我搜索了Stack Overflow,找到了建议使用计时器的答案:

struct CurrentDateView : View {
    @State var now = Date()

    let timer = Timer.publish(every: 1, on: .current, in: .common).autoconnect()

    var body: some View {
        Text("\(now)")
            .onReceive(timer) {
                self.now = Date()
            }
    }
}

但是我应该如何合并这些内容,以便可以使用类似@State的内容,在7.5秒后将值更改为false

@State randomTF : Bool = true

或在7.5秒后将Text("Please Enter Above")更改为Text("Sorry Too Late")

e37o9pze

e37o9pze1#

创建一个延迟,然后在时间过去后将@State属性hasTimeElapsed设置为true,从而更新视图体。
有了Swift 5.5和新的并发更新(asyncawait),您现在可以像下面这样使用task(_:)

struct ContentView: View {
    @State private var hasTimeElapsed = false

    var body: some View {
        Text(hasTimeElapsed ? "Sorry, too late." : "Please enter above.")
            .task(delayText)
    }

    private func delayText() async {
        // Delay of 7.5 seconds (1 second = 1_000_000_000 nanoseconds)
        try? await Task.sleep(nanoseconds: 7_500_000_000)
        hasTimeElapsed = true
    }
}

请在this answer中查看有关Task.sleep(nanoseconds:)的更多信息。

旧版本

Xcode 13.0+现在支持并发,向后兼容!然而,这里仍然是'老'的方法来做到这一点:
你可以使用DispatchQueue来延迟一些东西。用onAppear(perform:)来触发它(当视图第一次出现时发生)。如果需要的话,你也可以把延迟挂接到一个按钮上。
示例:

struct ContentView: View {
    @State private var hasTimeElapsed = false

    var body: some View {
        Text(hasTimeElapsed ? "Sorry, too late." : "Please enter above.")
            .onAppear(perform: delayText)
    }

    private func delayText() {
        // Delay of 7.5 seconds
        DispatchQueue.main.asyncAfter(deadline: .now() + 7.5) {
            hasTimeElapsed = true
        }
    }
}
9lowa7mx

9lowa7mx2#

.delay内置于Swift动画中,我实现了在视图出现0.5秒后启动动画的目标,代码如下:

.onAppear(perform: {
    withAnimation(Animation.spring().delay(0.5)) {
         self.scale = 1.0
    }
 })
u0sqgete

u0sqgete3#

//添加1秒的延迟

DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
   // your function
}
50few1ms

50few1ms4#

它可以是简单的:

Text("\(now)")
.onAppear(delay: 1) {
    self.now = Date()
}

使用这些扩展,它们可以在项目间重用,并且还可以解决一些相关问题:

public extension TimeInterval {
    var nanoseconds: UInt64 {
        return UInt64((self * 1_000_000_000).rounded())
    }
}

@available(iOS 13.0, macOS 10.15, *)
public extension Task where Success == Never, Failure == Never {
    static func sleep(_ duration: TimeInterval) async throws {
        try await Task.sleep(nanoseconds: duration.nanoseconds)
    }
}

@available(iOS 15.0, macOS 12.0, *)
public extension View {
    func onAppear(delay: TimeInterval, action: @escaping () -> Void) -> some View {
        task {
            do {
                try await Task.sleep(delay)
            } catch { // Task canceled
                return
            }
            
            await MainActor.run {
                action()
            }
        }
    }
}

相关问题