Post

Replies

Boosts

Views

Activity

Reply to App crashes after multiple transitions to screen containing AR Kit using SwiftUI NavigationStack
I am so sorry. I made a very silly mistake. I thought I had terminated the task when I left the screen, but I did not terminate it properly. By properly terminating the infinite loop when I left the screen, this problem no longer occurs. The loops were running multiple and endless times and just using up memory class Coordinator: NSObject, ARSCNViewDelegate, ARSessionDelegate, ARCoachingOverlayViewDelegate { var scanTargetTask: Task<Void, Never>? var isComplete: Bool = false @MainActor func scanTarget() { if scanTargetTask != nil { return } scanTargetTask = Task { let timer: AsyncTimerSequence = AsyncTimerSequence( interval: .seconds(0.05), clock: .continuous ) let _: AsyncStream = AsyncStream<Any> { continuation in if isComplete { continuation.yield(1) continuation.finish() } else { Task { for await _ in timer { if isComplete { return } updateFocusSquare() } } } } } } func stopScanTarget() { guard let scanTargetTask else { return } print("stopScanTarget") scanTargetTask.cancel() self.scanTargetTask = nil } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Mar ’25
Reply to App crashes after multiple transitions to screen containing AR Kit using SwiftUI NavigationStack
The following process calls the screen import SwiftUI internal struct ListView: View { @State private var scanData: ScanData = ScanData() var body: some View { NavigationStack { List { ListItem( title: "shoulder width", description: "scan shoulder max width", length: $scanData.shoulderWidth ) .overlay { NavigationLink(value: ScanType.shoulderWidth) { EmptyView() } .opacity(0) } .listRowBackground(Color.white) .listRowSeparator(.hidden) ListItem( title: "forearm width", description: "scan forearm max width", length: $scanData.forearmWidth ) .overlay { NavigationLink(value: ScanType.shoulderWidth) { EmptyView() } .opacity(0) } .listRowBackground(Color.white) .listRowSeparator(.hidden) ListItem( title: "knee thickness", description: "scan knee thickness", length: $scanData.kneeThicknessWidth ) .overlay { NavigationLink(value: ScanType.shoulderWidth) { EmptyView() } .opacity(0) } .listRowBackground(Color.white) .listRowSeparator(.hidden) } .listStyle(.plain) .navigationDestination(for: ScanType.self) { type in MeasureARView( title: "scan for ", bodyImageName: "PersonForearm", startPointBackgroundImageName: "BackgroundForearm", endPointBackgroundImageName: "BackgroundForearmEnd", startPointExplainText: "Tap the start point. Move the cursor and tap the button at the point", lastResult: nil, mode: .width, bindLength: type == .foreArm ? $scanData.forearmWidth : type == .knee ? $scanData.kneeThicknessWidth : type == .shoulderWidth ? $scanData.shoulderWidth : .constant(nil) ) } } } } import ARKit import AVFoundation import SwiftUI internal struct MeasureARView: View { let synthesizer: AVSpeechSynthesizer = AVSpeechSynthesizer() let title: String let bodyImageName: String let startPointBackgroundImageName: String let endPointBackgroundImageName: String let startPointExplainText: String let lastResult: Double? let mode: MeasurementMode @Binding var bindLength: Double? @State private var length: Double? @State private var tapCount: Int = 0 @State private var currentIndex: Int = 0 @Environment(\.dismiss) private var dismiss: DismissAction init( title: String, bodyImageName: String, startPointBackgroundImageName: String, endPointBackgroundImageName: String, startPointExplainText: String, lastResult: Double?, mode: MeasurementMode, bindLength: Binding<Double?> ) { self.title = title self.bodyImageName = bodyImageName self.startPointBackgroundImageName = startPointBackgroundImageName self.endPointBackgroundImageName = endPointBackgroundImageName self.startPointExplainText = startPointExplainText self.lastResult = lastResult self.mode = mode self.currentIndex = mode.rawValue self._bindLength = bindLength } var body: some View { ZStack { MeasureARViewContainer( tapCount: $tapCount, distance: $length, currentIndex: $currentIndex ) GeometryReader { geometry in SegmentedPicker( width: geometry.size.width, contents: ["thickness", "width"], selection: $currentIndex ) Image(tapCount == 0 ? startPointBackgroundImageName : endPointBackgroundImageName) .resizable() .frame(width: geometry.size.width, height: geometry.size.height) .accessibility(label: Text("imageIcon")) .opacity(0.5) } Text("+") .font(.largeTitle) .foregroundStyle(.red) .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) VStack { Image(bodyImageName, label: Text(bodyImageName)) .resizable() .frame(width: 30, height: 80) } .padding() .background(Color.black.opacity(0.6)) .cornerRadius(10) .foregroundColor(.white) .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottomLeading) .padding() Button(action: { withAnimation { tapCount += 1 } }, label: { ZStack { Circle() .foregroundStyle(Color.black.opacity(0.6)) .frame(width: 60, height: 60) Circle() .foregroundStyle(Color.black.opacity(0.6)) .frame(width: 80, height: 80) } }) .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom) .padding(.vertical) .alert("result", isPresented: Binding<Bool>( get: { $length.wrappedValue != nil }, set: { newValue in if !newValue { $length.wrappedValue = nil } } )) { Button("re scan") { length = nil tapCount = 0 } Button("register") { bindLength = length dismiss() } } message: { if let length { Text( """ result: \("\("\(String(format: "%0.1f", length)) cm")") """ ) } } } .navigationTitle( Text(title) ) } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Mar ’25