ios – My App crashes run-time sometimes after I use AVFoundation and associated code

0
16
ios – My App crashes run-time sometimes after I use AVFoundation and associated code


I’m creating an app for Automobile homeowners with a built-in map navigation characteristic with voice navigation assist. The app works high-quality with out voice navigation however after I use voice navigation it sometimes crashes and it crashes whereas voice navigation is just not in progress.

What makes it inconceivable to diagnose is that regardless that it crashed 10 instances on the TestFlight, I do not see any crash studies in ‘Apple Join’. I attempted working it in a simulator and it did not crash there! however on an actual gadget, after I drive with the app navigating me it crashes abruptly after a couple of minutes and it isn’t whereas the voice navigation is talking! I additionally ran the app with out AVFoundation and it didn’t crash then. So I’m 100% certain it’s one thing with this AVFoundation framework.

If anybody might help discover the issue in my following code it might be actually useful.

//
//  DirectionsView.swift
//  Map
//
//  Created by saj panchal on 2023-12-10.
//

import SwiftUI
///framework to document, playback and stream parsing. Additionally supplies interfaces to handle audio classes
//import AudioToolbox
///framework that accommodates duties to examine, play, seize and course of the audio video content material.
import AVFoundation
///a view accountable to point out the route indicators together with the instruction textual content on high of the display screen whereas navigating.
struct DirectionHeaderView: View {
    ///setting variable to get the colour mode of the cellphone
    @Setting(.colorScheme) var bgMode: ColorScheme
    ///variable that shops the picture title for varied route indicators.
    var directionSign: String?
    ///shops distance from the following step in string format.
    var nextStepDistance: String
    ///shops the instruction string.
    var instruction: String
    ///flag that's certain to MapSwiftUI. it's set when person faucets on this view to see the expanded instructions checklist view.
    @Binding var showDirectionsList: Bool
    @Binding var peak: CGFloat
    ///locationDataManager is an occasion of a category that has a delegate of LocationManager and its strategies.
    @StateObject var locationDataManager: LocationDataManager
    ///AVSpeechSynthesizer class is accountable to create a synthesized speech from textual content utterances. it additionally play, pause or cease the speech based mostly on the necessities.
    @State personal var synthesizer = AVSpeechSynthesizer()
    ///AVAudioSession is accountable to create an audio session sharedInstance that acts as a mediator between this app and the cellphone os. And, it creates an audio session based mostly on the preferences.
    @State personal var audioSession = AVAudioSession.sharedInstance()
    @State personal var lastInstruction: String = ""
    @State personal var utteranceDistance: String = ""
    @State personal var isStepExited = false
    @State personal var vary = 20.0
    var physique: some View {
        VStack {
            ///enclosing the instructions and instruction view in horizontal stack.
            HStack {
                ///reveals route signal and subsequent step distance beneath it.
                VStack {
                    ///if directionSign is just not empty present the picture.
                    if let directionSign = directionSign {
                        Picture(systemName: directionSign)
                            .font(.title)
                            .fontWeight(.black)
                            .padding(.high, 5)
                            .foregroundStyle(.grey)
                        
                    }
                    ///present the gap from subsequent step
                    if !instruction.accommodates("Re-calculating the route...") {
                        Textual content("(nextStepDistance)")
                            .padding(.backside, 5)
                            .font(.title2)
                            .fontWeight(.black)
                            .foregroundStyle(Colour(AppColors.invertRed.rawValue))
                            .onChange(of: nextStepDistance) {
                                let distance = getDistanceInNumber(distance: nextStepDistance)
                            
                                if distance <= vary && !isStepExited {
                                    startVoiceNavigation(with: instruction)
                                    isStepExited = true
                                }
                                
                            }
                    }
                    
                }
                ///add an area between instructions and instruction stacks.
                Spacer()
                    ///exhibiting the instruction in a textual content format
                    Textual content(instruction)
                    .onAppear {
                        print("instruction Seem")
                        isStepExited = false
                        ///set the utteranceDistance by the up to date subsequent step distance on seem of instruction textual content
                        utteranceDistance = nextStepDistance
                         vary = nextStepRange(distance: utteranceDistance)
                        print("Step vary: ( vary), Velocity: (locationDataManager.pace)")
                        ///begin voice navigation with the utterance.
                        startVoiceNavigation(with: "In (utteranceDistance), (instruction)")
                    }
                    .onChange(of: instruction) {
                        print("On change of instruction")
                        isStepExited = false
                        ///set the utteranceDistance by the up to date subsequent step distance on replace of instruction textual content
                        utteranceDistance = nextStepDistance
                        vary = nextStepRange(distance: utteranceDistance)
                        print("Step vary: ( vary), Velocity: (locationDataManager.pace)")
                        startVoiceNavigation(with: "In (utteranceDistance), (instruction)")
                    }
                        .padding(10)
                        .font(.title3)
                        .fontWeight(.black)
                        .foregroundStyle(.grey)
                ///add a spacer to the fitting of the instruction view.
                Spacer()
            }
            if !showDirectionsList {
                ExpandViewSymbol()
            }
        }
        .onAppear {
            print("directionview appeared")
           // setupAudioSession()
     
        }
        
        .padding(.horizontal,10)
        ///apply the black gradient to whole view.
        .background(bgMode == .darkish ? Colour.black.gradient : Colour.white.gradient)
    }
    func startVoiceNavigation(with utterance: String) {
       ///if instruction is empty return the operate name
        if instruction.isEmpty || utterance.isEmpty {
            print("instruction empty")
            return
        }
        if instruction.accommodates("Re-calculating the route...") {
            synthesizer.stopSpeaking(at: AVSpeechBoundary.fast)
            return
        }
        ///create a speech utterance occasion from utterance string
        let thisUttarance = AVSpeechUtterance(string: utterance)
        ///save the present instruction as final obtained instruction
        lastInstruction = instruction
       ///ensuring the audio session is about the a given class and choices
        if audioSession.class == .playback && audioSession.categoryOptions == .mixWithOthers {
            DispatchQueue.important.async {
                ///command synthesizer to talk the utterance
                synthesizer.converse(thisUttarance)
                print("Talking...(synthesizer.isSpeaking) (instruction)")
            }
        }
        ///if audio session is just not configured.
        else {
            ///setup the audio session
            setupAudioSession()
            ///command the synthesizer to talk.
            DispatchQueue.important.async {
                synthesizer.converse(thisUttarance)
            }
            print("Talking once more...")
        }
    }
    
    func setupAudioSession() {
        do {
            attempt audioSession.setCategory(AVAudioSession.Class.playback, choices: AVAudioSession.CategoryOptions.mixWithOthers)
            attempt audioSession.setActive(true)
            print("audio session is created.")
        }
        catch {
            print("error:(error.localizedDescription)")
        }
    }
    
    func nextStepRange(distance: String) -> Double {
        var thisStepDistance = getDistanceInNumber(distance: distance)

        if thisStepDistance != 0 {
            change thisStepDistance {
            case 0...200:
                if locationDataManager.pace >= 90 {
                    return thisStepDistance/1.5
                }
                else {
                    return thisStepDistance/2
                }
            case 201...300:
                if locationDataManager.pace >= 90 {
                    return 120
                }
                else {
                    return 100
                }
            case 301...500:
                if locationDataManager.pace >= 90 {
                    return 150
                }
                else {
                    return 125
                }
            case 501...1000:
                if locationDataManager.pace >= 90 {
                    return 250
                }
                else {
                    return 200
                }
            case 1001...10000:
                if locationDataManager.pace >= 90 {
                    return 250
                }
                else {
                    return 200
                }
            
            default:
                if locationDataManager.pace >= 90 {
                    return 250
                }
                else {
                    return  200
                }
              
            }
        }
      
        return 200
    }
    func getDistanceInNumber(distance: String) -> Double {
        var thisStepDistance = 0.0
        if distance.accommodates("km") {
            let stepDistanceSplits = distance.break up(separator: " ")
            let stepDistanceText = String(stepDistanceSplits[0])
            if let dist = Double(stepDistanceText) {
                thisStepDistance = dist * 1000
            }
          
        }
        else {
            var stepDistanceSplits = distance.break up(separator: " ")
            var stepDistanceText = String(stepDistanceSplits[0])
            if let dist = Double(stepDistanceText) {
                thisStepDistance = dist               
            }
        }
        print("Transformed quantity: (thisStepDistance)")
        return thisStepDistance
    }
}

#Preview {
    DirectionHeaderView(directionSign: "", nextStepDistance: "", instruction: "", showDirectionsList: .fixed(false), peak: .fixed(0), locationDataManager: LocationDataManager())
}

LEAVE A REPLY

Please enter your comment!
Please enter your name here