Silhouette
Silhouette

Reputation: 11

Add Bluetooth LE midi to my ios APP using audiokit’s midi

Recently, I want to to add Bluetooth midi support to my app, and I use the audiokit’s BluetoothMIDIbutton, which code can be found here https://github.com/AudioKit/AudioKit/blob/main/Sources/AudioKit/MIDI/BluetoothMIDIButton.swift. Because my UI is based on SwiftUI, and I use the UIRepresentable to bridge the UIView to my swiftUI View, after I add NSBluetoothAlwaysUsageDescription and NSBluetoothPeripheralUsageDescription, I can run this app and connect to my mac, after a while, this app lose the connection with my Mac, the console will print API MISUSE: Cancelling connection for unused peripheral <CBPeripheral: , identifier = , name = My MacBook Pro, mtu = 23, state = connecting>, Did you forget to keep a reference to it? and XPC connection invalid. I have searched for solutions, which recommend me to add a strong reference to my ViewController? I donnot know how to add it properly, and my code goes like this , you can run directly by copying it and add NSBluetoothAlwaysUsageDescription and NSBluetoothPeripheralUsageDescription in the info.plist, and run it in a physical device. How could I do to fix this problem and run it properly.

import SwiftUI
import CoreAudioKit

struct BTMIDIView: UIViewControllerRepresentable {
    @Environment(\.presentationMode) var presentationMode
    
 
    func makeUIViewController(context: Context) -> UINavigationController {
        let controller = BTMIDICentralViewController()
        let nav = UINavigationController(rootViewController: controller)
        //        nav.modalPresentationStyle = .none
        return nav
    }
    

    func updateUIViewController(_ uiViewController: UINavigationController, context: Context) {}
    
   
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject {
        var parent: BTMIDIView
        
        init(_ parent: BTMIDIView) {
            self.parent = parent
        }
    }
}

class BTMIDICentralViewController: CABTMIDICentralViewController {
    

    @objc func doneAction() {
        dismiss(animated: true)
    }
    

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        navigationItem.rightBarButtonItem = UIBarButtonItem(
            barButtonSystemItem: .done,
            target: self,
            action: #selector(doneAction)
        )
    }
}

struct BluetoothMIDIControlView: View {
    @State private var showMIDISetup = false
    @EnvironmentObject var mainViewModel: MainViewModel
    
    var body: some View {
        ZStack(alignment: .top) {
      
            Color(.systemBackground)
                .ignoresSafeArea()
            
            VStack(spacing: 20) {
                Toggle("BLE MIDI", isOn: $mainViewModel.isBluetoothMIDIEnabled)
                    .toggleStyle(SwitchToggleStyle(tint: .blue))
                    .padding(.horizontal)
                    .onChange(of: mainViewModel.isBluetoothMIDIEnabled) { newValue in
                        handleMIDIToggle(newValue: newValue)
                    }
                
      
                if mainViewModel.isBluetoothMIDIEnabled {
                    BTMIDIView()
                        .frame(height: 400) 
                        .background(Color(.systemBackground)) 
                        .cornerRadius(12)
                        .shadow(radius: 5)
                     .padding()
                } else {
    
                    Color.clear.frame(height: 400)
                }
            }
        }
        
        
        
    }
    

    private func handleMIDIToggle(newValue: Bool) {
        if newValue {
            showMIDISetup = true
        } else {

            print("BLE MIDI closed")
        }
    }
}

#Preview {
    let mainVM = MainViewModel()
    BluetoothMIDIControlView()
        .environmentObject(mainVM)
        
}

Upvotes: 1

Views: 19

Answers (0)

Related Questions