Saturday, March 25, 2023
HomeiOS Developmentios - SwiftUI sheet reappears after dismissed on Apple Watch

ios – SwiftUI sheet reappears after dismissed on Apple Watch


I am growing a health app for the Apple Watch that allows you to select an depth earlier than beginning a exercise. I wish to current the depth picker earlier than the exercise begins, so I attempted presenting it as a sheet earlier than navigating to the precise exercise view. The issue is that when I attempt to dismiss the sheet, it’s dismissed however it comes proper again. I am utilizing Xcode 14.2 and watchOS 9.1.

That is the principle view and in addition the view that presents the mentioned sheet (the primary one, managed by showingZonePickerView):

import SwiftUI

@major
struct Wise_Watch_AppApp: App {
    @StateObject non-public var workoutManager = WorkoutManager()

    @SceneBuilder var physique: some Scene {
        WindowGroup {
            NavigationView {
                WorkoutView()
            }
            .sheet(isPresented: $workoutManager.showingZonePickerView, onDismiss: {
                workoutManager.showingZonePickerView = false
            }) {
                WorkoutLevelPickerView(complete: 5, accomplished: 1)
                    .toolbar(.hidden)
            }
            .sheet(isPresented: $workoutManager.showingSummaryView) {
                SummaryView()
            }
            .environmentObject(workoutManager)
        }
    }
}

That is the view the place the person can decide the popular exercise:

import SwiftUI
import HealthKit

struct WorkoutView: View {
    @EnvironmentObject var workoutManager: WorkoutManager
    
    @State var linkActive: Bool = false

    var workoutTypes: [HKWorkoutActivityType] = [.cycling, .running, .walking]
    var workoutDictionary: Dictionary<String, HKWorkoutActivityType> = [
        "figure.outdoor.cycle" : .cycling,
        "figure.run" : .running,
        "figure.walk" : .walking
    ]

    var physique: some View {
        Record(Array(workoutDictionary.keys), id: .self) { workoutType in
            NavigationLink(
                vacation spot: SessionPagingView(),
                tag: workoutDictionary[workoutType]!,
                choice: $workoutManager.selectedWorkout
            ) {
                Label("(workoutDictionary[workoutType]!.title)", systemImage: workoutType)
                    .font(.subheadline)
                    .fontWeight(.semibold)
                    .padding()
            }
            .padding(EdgeInsets(prime: 15, main: 5, backside: 15, trailing: 5))
        }
        .listStyle(.carousel)
        .navigationBarTitle("Exercises")
        .onAppear {
            workoutManager.requestAuthorization()
        }
    }
}

That is the view to which the app navigates when a NavigationLink is pressed:

import SwiftUI
import WatchKit
import ConfettiSwiftUI

struct SessionPagingView: View {
    @EnvironmentObject var workoutManager: WorkoutManager
    @State non-public var choice: Tab = .metrics
    @State non-public var counter: Int = 0
    @State non-public var isViewHidden: Bool = true

    enum Tab {
        case metrics, nowPlaying, milestone
    }

    var physique: some View {
        if(isViewHidden) {
            sessionView.hidden()
        } else {
            sessionView
        }
    }
    
    var sessionView: some View {
        TabView(choice: $choice) {
            ForEach(workoutManager.tabItems) { merchandise in
                VStack {
                    Textual content("Congrats!")
                        .font(.title2)
                        .fontWeight(.daring)
                        .confettiCannon(counter: $counter, num: 40, radius: 200)
                    Textual content("You simply reached")
                        .font(.subheadline)
                        .foregroundColor(.cyan)
                        .tag(Tab.milestone)
                    Textual content("(merchandise.worth) km")
                        .font(.subheadline)
                        .foregroundColor(.cyan)
                        .tag(Tab.milestone)
                }
                
            }
            MetricsView().tag(Tab.metrics)
            NowPlayingView().tag(Tab.nowPlaying)
        }
        .navigationBarHidden(true)
        .navigationBarBackButtonHidden(true)
        .onAppear {
            workoutManager.showingZonePickerView = true
            DispatchQueue.major.asyncAfter(deadline: .now() + 1) {
                self.isViewHidden = false
            }
        }
        .onChange(of: workoutManager.working) { _ in
            displayMetricsView()
        }
        .onChange(of: workoutManager.tabItems) { _ in
            if(workoutManager.tabItems.depend > 0) {
                displayMilestoneView()
                DispatchQueue.major.asyncAfter(deadline: .now() + .seconds(5), execute: {
                    displayMetricsView()
                })
            }
        }
        .ignoresSafeArea()
        .animation(.easeInOut, worth: self.choice)
    }

    non-public func displayMetricsView() {
        withAnimation {
            choice = .metrics
        }
    }
    
    non-public func displayMilestoneView() {
        withAnimation {
            choice = .milestone
            WKInterfaceDevice.present().play(.notification)
            DispatchQueue.major.asyncAfter(deadline: .now() + .seconds(1), execute: {
                counter += 1
            })
        }
    }
}

That is the precise view that I am presenting contained in the sheet:

import SwiftUI

struct WorkoutLevelPickerView: View {
    @EnvironmentObject var workoutManager: WorkoutManager
    @Setting(.dismiss) non-public var dismiss
    
    let complete: Int
    
    @State var lineWidth: CGFloat = 16
    @State var colour: Shade = .inexperienced
    @State var accomplished: Double = 1.0
    @State var currentZone: HeartRateZone = zones[0]
    @State var isScrolling: Bool = false
    
    var physique: some View {
        VStack {
            ZStack {
                CircleLabelView(
                    radius: 30,
                    monitoring: 0,
                    dimension: .init(width: 120, top: 120),
                    textual content: currentZone.depth.uppercased()
                )
                .font(.headline)
                .body(width: 50, top: 50)
                .rotationEffect(Angle(levels: Double(currentZone.labelRotationAngleModifier * currentZone.depth.depend / 2)))
                .opacity(isScrolling ? 0 : 1)
                .animation(.easeInOut, worth: isScrolling)
                
                WorkoutLevelPickerBackgroundView(complete: complete, lineWidth: lineWidth)
                withAnimation(.spring()) {
                    WorkoutLevelPickerProgressView(complete: complete, accomplished: Int(accomplished), lineWidth: lineWidth, zone: currentZone)
                }
                VStack {                    
                    Button {
                        dismiss()
                    } label: {
                        Picture(systemName: currentZone.iconName)
                            .padding()
                            .font(.title2)
                    }
                    .body(width: 70, top: 70)
                }
            }
            .body(width: 150, top: 150)
            .focusable()
            .digitalCrownRotation(
                detent: $accomplished.animation(.spring()),
                from: 1.0,
                via: 5.0,
                by: 1.0,
                sensitivity: .low,
                isContinuous: false,
                isHapticFeedbackEnabled: true,
                onChange: { _ in
                    isScrolling = true
                },
                onIdle: {
                    isScrolling = false
                }
            )
            .digitalCrownAccessory(.hidden)
            .onChange(of: accomplished) {_ in
                if(Int(accomplished) != currentZone.id) {
                    currentZone = zones[Int(completed) - 1]
                    print(currentZone.tint.description)
                }
            }
        }
        
    }
}

It is a video of the stream that generates my drawback:

Illustration of the problem in the simulator

I attempted presenting the sheet from different views. I additionally tried dismissing the sheet via a binding, not via the dismiss motion. On all these modifications, the result was the identical as earlier than.

Edit:

Forgot to say that, when the sheet is introduced, urgent the facet button will dismiss it and the app will work as supposed till the person tries to start out a brand new exercise.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments