You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift Playgrounds中获取外接MIDI设备名称失败求助

Swift Playgrounds中MIDI设备无法识别的修复方案

你的代码无法获取MIDI设备列表的核心原因是未初始化CoreMIDI客户端——CoreMIDI要求必须先创建一个活跃的MIDI客户端,才能枚举系统中的MIDI设备。直接调用MIDIGetNumberOfDevices会返回0,因为没有客户端上下文。

修复后的完整代码

import SwiftUI
import CoreMIDI

struct ContentView: View {
    @State private var selectedDevice: String = ""
    @State private var deviceList: [String] = []
    
    var body: some View {
        VStack {
            TextField("Selected Device", text: $selectedDevice)
                .padding()
            
            Button("Select Device") {
                self.deviceList = getMIDIDeviceList()
            }
            .padding()
            
            // 新增:展示获取到的设备列表,支持点击选择
            List(deviceList, id: \.self) { name in
                Text(name)
                    .onTapGesture {
                        selectedDevice = name
                    }
            }
        }
    }
    
    private func getMIDIDeviceList() -> [String] {
        var deviceNames = [String]()
        var midiClient: MIDIClientRef = 0
        let clientName = "MIDIDeviceScanner" as CFString
        
        // 1. 创建MIDI客户端,这是枚举设备的必要前提
        let createResult = MIDIClientCreate(clientName, nil, nil, &midiClient)
        guard createResult == noErr else {
            print("创建MIDI客户端失败:\(createResult)")
            return deviceNames
        }
        
        // 2. 枚举所有MIDI设备并提取名称
        let numberOfDevices = MIDIGetNumberOfDevices()
        for index in 0..<numberOfDevices {
            let device = MIDIGetDevice(index)
            var name: Unmanaged<CFString>?
            let propertyResult = MIDIObjectGetStringProperty(device, kMIDIPropertyName, &name)
            
            if propertyResult == noErr, let name = name {
                deviceNames.append(name.takeUnretainedValue() as String)
                name.release() // 释放Unmanaged对象,避免内存泄漏
            }
        }
        
        // 3. 销毁客户端(若需持续监听设备可保留客户端实例)
        MIDIClientDispose(midiClient)
        
        return deviceNames
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

关键修改说明

  • 初始化MIDI客户端:通过MIDIClientCreate创建客户端上下文,这是CoreMIDI访问设备的硬性要求,没有客户端则无法获取任何设备信息。
  • 错误检查:添加客户端创建和属性读取的错误判断,便于排查异常情况。
  • 内存管理:调用name.release()释放Unmanaged<CFString>对象,避免内存泄漏。
  • 可视化设备列表:新增List组件展示获取到的设备,解决原代码仅用TextField无法查看结果的问题。

额外提示

  • 确保iPad已正确连接MIDI设备(蓝牙或有线),且设备处于活跃状态。
  • 若需要实时监听设备连接/断开事件,可通过MIDINotificationCreate注册通知回调,替代手动点击枚举的方式。

内容的提问来源于stack exchange,提问作者Jpm47

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 03:52:21