SwiftUI: перерисовка на устройстве ориентация делает недействительным таймер - PullRequest
0 голосов
/ 14 апреля 2020

Я делаю секундомер, используя SwiftUI.

Я перекрашиваю пользовательский интерфейс при изменении ориентации в целях проектирования, но это делает мой таймер недействительным. Я использовал одно из этих решений

Как мне сохранить мой таймер при изменении ориентации?

Вот модель:

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 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"
    }
}

Edit Вот как секундомер используется в представлении

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
                )
            }
        }
    }
}

1 Ответ

1 голос
/ 15 апреля 2020

Поскольку ваше StopWatch является свойством в вашем представлении, новый экземпляр вашего секундомера создается каждый раз, когда создается новый экземпляр вашего представления, например, когда изменяется макет устройства.

Ваш секундомер должен быть собственностью вашего Model. Ваш экземпляр Model живет в среде, поэтому его время жизни - это время жизни контроллера представления хоста:

class Model: ObservableObject {
    @Published var isLandScape: Bool = false
    @Published var isPhone: Bool =  UIDevice.current.userInterfaceIdiom == .phone
    @Published var isPhoneAndLandscape: Bool = false;
    var stopwatch = StopWatch()
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...