How & where to implement shake detection with SwiftUI?

Viewed 319

I am trying to implement a shake detection with SwiftUI. So far I created a ViewController which conforms to UIViewControllerRepresentable. That way I can use my ViewController with SwiftUI. Additionally I am conforming to AVAudioPlayerDelegate in the Coordinator class.

In this VC I would now like to detect a detection if the device was shaken. Without SwiftUI I would just implement func motionBegan(UIEvent.EventSubtype, with: UIEvent?) and be basically done.

Where do I implement this function now? I am a bit lost at this point. Here is my code so far:

struct SoundViewController: UIViewControllerRepresentable {
    var audioPlayer: AVAudioPlayer?

    func makeCoordinator() -> Coordinator { // SwiftUI calls this makeCoordinator() method before makeUIViewController(context:), so that you have access to the coordinator object when configuring your view controller.
        return Coordinator(self)
    }

    func makeUIViewController(context: Context) -> UIViewController {
        return UIViewController()
    }

    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
        // TODO
    }

    class Coordinator: NSObject, AVAudioPlayerDelegate {
        var parent: SoundViewController

        init(_ soundViewController: SoundViewController) {
            self.parent = soundViewController
        }

        func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
            print("audioPlayerDidFinishPlaying Delegate")
            if flag {
                if parent.audioPlayer != nil {
                    parent.audioPlayer = nil
                }
            }
        }
    }
}

Thanks a lot!

1 Answers

I would recommend to solve your issue like this:

  1. Rename your SoundViewController to SoundView or SoundViewControllerRepresentable. This serves two purposes: It prevents confusion as this is resembles a view in terms of SwiftUI, not a view controller in terms of UIKit. Also, we might want to use that name for an actual view controller in the next step.

  2. Create a customer view controller class (e.g. SoundViewController) and override UIResponder.motionBegan(_:with:) (UIViewController conforms to UIResponder). More hints can be found in SwiftUI and Shake Gesture on Medium.

  3. Adjust your SwiftUI view's makeViewController(context:) to create an instance of SoundViewController instead of UIViewController.

  4. Connect whatever action you want to perform with the SoundViewController so it will be executed for every device shake recognized.

Related