ios – Volume button events are delayed until after block is done


I have this iOS app in Swift that lets the user take a picture, send it to a server with an API and retrieve a response. The letters in the response are converted into vibrations that the user can feel using Apple’s CHHapticEngine. I’m also using a github library called JPSVolumeButtonHandler that listens for volume button presses and does something when it detects one. I want to cancel the vibrations when the user presses one of the volume buttons if the response happens to be too long. The problem I’m facing is that when the app is playing the vibrations no volume button presses are being detected and so I can’t cancel the vibrations. It is only after the vibrations are done that the events are registered.
I haven’t implemented any cancelation yet and have only tried to get the volume buttons to be detected.
I can supply the additional functions that creates the haptics as well.

Code in the ImagePicker gets executed after a response is retrieved.

import SwiftUI
import JPSVolumeButtonHandler
import AVFoundation
import Corehaptics

struct ContentView: View {
@State private var hapticEngine: CHHapticEngine?
@State private var volumeHandler: JPSVolumeButtonHandler?
@State private var ohwow: String = ""
//other @State private variables

//other code

.sheet(isPresented: $isImagePickerPresented, onDismiss: {
                
}) {
   
    ImagePicker(image: $capturedImage, onImageCapture: { imageData in
                    
        if let imageData = imageData{
                            
            uploadImage(imageData: imageData, serverURL: userInput) { result in
                                
                print("inside closure")

                    switch result {
                        case .success(let responseString):
                            print("success")
                            ohwow = extractedText(responseString) ?? "bad response"
                            ohwow = ohwow.lowercased()
                            print(ohwow.count)
                            vibro = true
                                    
                            viewModel.isConditionTrue = true
                            
                            finishedstring = morseOhwow(ohwow) //translates the string into morse code which is played through vibrations.
                            print("response:\"\(ohwow)\"")

                        case .failure(let error):
                            print("Error: \(error)")
                                }   
                            }         
                        }
                    })
            }

The Volume Button Handler

VStack{
Text()
//Other stuff
}

.onAppear {

    print("onappear")
                
    setupHaptics()

    //setupHaptics()
    /*
    public func setupHaptics() {
        print("setupHaptics call")
            do {
                hapticEngine = try CHHapticEngine()
                try hapticEngine?.start()
            } catch {
                print("Error initializing haptic engine: \(error)")
            }
        }
    */
                
    observeCondition()
               
    volumeHandler = JPSVolumeButtonHandler(up: {
        DispatchQueue.main.async{ //I don't think this is necessary but I added it for testing
                        
        if self.vibro{
            print("vibro is true")
        }

        else{
            isImagePickerPresented.toggle()
        }
                        
        print("DETECTED")
                       
        }
                    
    }, 
downBlock: {
    //Same as the upblock
    }
                  
})
                
volumeHandler?.start(true)
                
}

I tried creating a boolean in the ImagePicker like in the code above so that instead of running a function inside imagepicker, it gets called by a different source when it detects a change in the boolean. This doesn’t work. I tried a lot with Dispatch.global().async and Dispatch.main.async to see if it could work because CHHapticEngine has to be run in the main thread and I think in the jps library source file it also runs on the main thread. So maybe this is a problem to do with concurrency?

Might be a longer question but any help would be appreciated!

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img