[英]SwiftUI: Repaint on Device orientation invalidates Timer
我正在使用 SwiftUI 制作秒表。
出于设计目的,我在方向更改时重新绘制 UI,但这会使我的计时器无效。 我使用了其中一种解决方案
如何在方向更改时保持计时器?
这是 model:
class Model: ObservableObject {
@Published var isLandScape: Bool = false
@Published var isPhone: Bool = UIDevice.current.userInterfaceIdiom == .phone
@Published var isPhoneAndLandscape: Bool = false;
}
自定义 UIHostingController:
extension Notification.Name {
static let my_onViewWillTransition = Notification.Name("MainUIHostingController_viewWillTransition")
}
class MyUIHostingController<Content> : UIHostingController<Content> where Content : View {
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
NotificationCenter.default.post(name: .my_onViewWillTransition, object: nil, userInfo: ["size": size])
super.viewWillTransition(to: size, with: coordinator)
}
}
我在 SceneDelegate 中使用的:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = MyUIHostingController(rootView: HomeView().environmentObject(model))
self.window = window
window.makeKeyAndVisible()
}
}
还有秒表 class:
class StopWatch: ObservableObject {
@Published var stopWatchTime: String = "00:00:00";
@Published var isPaused = true;
var timer = Timer()
private var counter: Int = 0
func start() {
isPaused.toggle();
timer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true) { timer in
self.counter += 1
self.stopWatchTime = StopWatch.convertCountToTimeString(counter: self.counter)
}
}
func pause() {
isPaused.toggle();
timer.invalidate()
}
func reset() {
self.timer.invalidate()
self.isPaused = true;
self.counter = 0;
self.stopWatchTime = "00:00:00"
}
}
编辑这是秒表在视图中的使用方式
struct StopWatchUI: View {
@ObservedObject var stopWatch = StopWatch()
@Binding var isSureToResetWatch: Bool;
@EnvironmentObject var model: Model
var body: some View {
return VStack {
Text(self.stopWatch.stopWatchTime)
.foregroundColor(.textPrimary)
.font(.custom("Courier",size: model.isPhoneAndLandscape ? 50 : 120))
.fontWeight(.heavy)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: nil, maxHeight: nil)
.padding(15)
.minimumScaleFactor(0.4)
.cornerRadius(5)
.lineLimit(1)
HStack {
StopWatchResetButton(isSureToResetWatch: $isSureToResetWatch, resetTime: self.stopWatch.reset)
Spacer()
StopWatchStartButton(
start: self.stopWatch.start,
pause: self.stopWatch.pause,
isStopWatchPaused: self.stopWatch.isPaused
)
}
}
}
}
由于StopWatch
是视图中的一个属性,因此每次创建视图的新实例时都会创建一个新的秒表实例,例如当设备布局更改时。
您的秒表应该是您的Model
的财产。 您的Model
实例存在于环境中,因此它的生命周期是托管视图 controller 的生命周期:
class Model: ObservableObject {
@Published var isLandScape: Bool = false
@Published var isPhone: Bool = UIDevice.current.userInterfaceIdiom == .phone
@Published var isPhoneAndLandscape: Bool = false;
var stopwatch = StopWatch()
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.