我怎样才能简单地将View过渡到SwiftUI View?

时间:2019-12-26 01:45:30

标签: ios swift timer swiftui swift5

我想通过SwiftUI和Timer实现一个简单的视图转换。 我有一个主视图,它是内容视图。如果从视图中调用func FireTimer(),该函数将触发计时器。然后5秒钟后,我将进行视图转换。

我尝试了NavigationLink,但是它有一个按钮。计时器不能按按钮,所以现在我很困惑。 我将在下面显示我的代码。

TimerFire.swift

import Foundation
import UIKit
import SwiftUI

let TIME_MOVENEXT = 5
var timerCount : Int = 0

class TimerFire : ObservableObject{
    var workingTimer = Timer()

    @objc func FireTimer() {
        print("FireTimer")
        workingTimer = Timer.scheduledTimer(timeInterval: 1,     
            target: self,                                        
            selector: #selector(TimerFire.timerUpdate),      
            userInfo: nil,                                   
            repeats: true)                                   
    }

    @objc func timerUpdate(timeCount: Int) {
        timerCount += 1
        let timerText = "timerCount:\(timerCount)"
        print(timerText)

        if timerCount == TIME_MOVENEXT {
            print("timerCount == TIME_MOVENEXT")

            workingTimer.invalidate()
            print("workingTimer.invalidate()")
            timerCount = 0

            //
            //want to have a transition to SecondView here
            //
        }
    }
}

ContentView.swift

import SwiftUI

struct ContentView: View {
    var body: some View {
        Button(action: {
            // What to perform
            let timerFire = TimerFire()
            timerFire.FireTimer()
        }) {
            // How the button looks like
            Text("Fire timer")
        }
    }
}

SecondView.swift

import Foundation
import SwiftUI

struct SecondView: View {
    var body: some View {
        Text("Second World")
    }
}

我如何简单地显示此SecondView?

2 个答案:

答案 0 :(得分:0)

ContentView没有代码段,因此我尝试自己构建一个简单的示例。您可以使用NavigationLink(destination: _, isActive: Binding<Bool>, label: () -> _)。从State接收更改时,请更改一些Timer.publish变量,您将立即转到SecondView

struct TransitionWithTimer: View {

    @State var goToSecondWorld = false
    let timer = Timer.publish(every: 5, on: .main, in: .common).autoconnect()

    var body: some View {

        NavigationView {
            VStack {
                NavigationLink(destination: SecondWorld(), isActive: self.$goToSecondWorld) {
                    Text("First World")
                        .onReceive(timer) { _ in
                            self.goToSecondWorld = true
                    }
                }

            }

        }

    }
}

// you can use ZStack and opacity/offset of view's:

struct TransitionWithTimerAndOffset: View {

    @State var goToSecondWorld = false
    let timer = Timer.publish(every: 3, on: .main, in: .common).autoconnect()

    var body: some View {

        ZStack {
            Text("First world") // here can be your first View
                .opacity(self.goToSecondWorld ? 0 : 1)
                .offset(x: goToSecondWorld ? 1000 : 0)

            Text("Second world") // and here second world View
                .opacity(self.goToSecondWorld ? 1 : 0)
                .offset(x: goToSecondWorld ? 0 : -1000)
        }
        .onReceive(timer) { _ in
            withAnimation(.spring()) {
                self.goToSecondWorld = true
            }

        }

    }

}

struct SecondWorld: View {
    var body: some View {
        Text("Second World")
    }
}

答案 1 :(得分:0)

好吧,如果您希望在第一个屏幕上不使用NavigationView来执行此操作(出于任何原因),这是一种基于两个视图之间的过渡的可行方法。

注意:预览版对转换的支持有限,因此请在模拟器和真实设备上进行测试

这是一个演示外观(初始白屏只是模拟器启动)

SwiftUI transition on timer

这里是单个测试模块:

import SwiftUI
import UIKit

let TIME_MOVENEXT = 5
var timerCount : Int = 0

class TimerFire : ObservableObject{
    var workingTimer = Timer()
    @Published var completed = false

    @objc func FireTimer() {
        print("FireTimer")
        workingTimer = Timer.scheduledTimer(timeInterval: 1,
            target: self,
            selector: #selector(TimerFire.timerUpdate),
            userInfo: nil,
            repeats: true)
    }

    @objc func timerUpdate(timeCount: Int) {
        timerCount += 1
        let timerText = "timerCount:\(timerCount)"
        print(timerText)

        if timerCount == TIME_MOVENEXT {
            print("timerCount == TIME_MOVENEXT")

            workingTimer.invalidate()
            print("workingTimer.invalidate()")
            timerCount = 0

            //
            //want to have a transition to SecondView here
            //
            self.completed = true
        }
    }
}

struct SecondView: View {
    var body: some View {
        Text("Second World")
    }
}

struct TestTransitionByTimer: View {
    @ObservedObject var timer = TimerFire()

    @State var showDefault = true
    var body: some View {
        ZStack {
            Rectangle().fill(Color.clear) // << to make ZStack full-screen
            if showDefault {
                Rectangle().fill(Color.blue) // << just for demo
                    .overlay(Text("Hello, World!"))
                    .transition(.move(edge: .leading))
            }
            if !showDefault {
                Rectangle().fill(Color.red) // << just for demo
                    .overlay(SecondView())
                    .transition(.move(edge: .trailing))
            }
        }
        .onAppear {
            self.timer.FireTimer()
        }
        .onReceive(timer.$completed, perform: { completed in
            withAnimation {
                self.showDefault = !completed
            }
        })
    }
}

struct TestTransitionByTimer_Previews: PreviewProvider {
    static var previews: some View {
        TestTransitionByTimer()
    }
}