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

iOS开发:MPVolumeView无法稳定显示听筒与扬声器选项问题

问题解决方案

问题1:无法始终显示iPhone听筒与扬声器选项

调整音频会话配置

当前音频会话的选项组合不足以让系统稳定显示听筒和扬声器选项,修改配置以支持多路由输出切换:

audioSession = AVAudioSession.sharedInstance()

do {
    // 结合.playAndRecord与多选项,确保支持蓝牙、默认扬声器输出,同时允许AirPlay
    try audioSession?.setCategory(.playAndRecord, options: [.allowBluetooth, .defaultToSpeaker, .allowAirPlay])
    try audioSession?.setActive(true)
} catch {
    print("Failed to set audio session category: \(error)")
}

NotificationCenter.default.addObserver(self, selector: #selector(routeChangeEventHandle), name: AVAudioSession.routeChangeNotification, object: nil)

优化MPVolumeView初始化逻辑

避免手动遍历子视图查找按钮,直接使用系统提供的routeButton属性,同时确保视图布局正确:

let volumeView = MPVolumeView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
volumeView.showsVolumeSlider = false
volumeView.tintColor = .gray

// 直接配置系统路由按钮
if let routeButton = volumeView.routeButton {
    let symbolConfiguration = UIImage.SymbolConfiguration(pointSize: 40, weight: .regular)
    let sfSymbol = UIImage(systemName: "airplayvideo.circle.fill", withConfiguration: symbolConfiguration)
    routeButton.setImage(sfSymbol, for: .normal)
    routeButton.frame = volumeView.bounds
}

self.vwMV.addSubview(volumeView)

路由变化时刷新视图

在路由切换通知回调中触发视图布局更新,确保选项实时同步:

@objc func routeChangeEventHandle(notification: Notification) {
    volumeView.setNeedsLayout()
    volumeView.layoutIfNeeded()
}

问题2:切换到扬声器后对话框显示“iPhone”需改为中文

系统默认MPVolumeView的弹窗文字无法直接修改,建议通过自定义路由选择弹窗完全控制选项文字:

1. 获取可用音频路由并映射中文名称

func getAvailableAudioRoutes() -> [(name: String, route: AVAudioSessionPortDescription)] {
    guard let outputs = AVAudioSession.sharedInstance().currentRoute.outputs else { return [] }
    
    var routes = [(name: String, route: AVAudioSessionPortDescription)]()
    for output in outputs {
        switch output.portType {
        case .builtInReceiver:
            routes.append((name: "听筒", route: output))
        case .builtInSpeaker:
            routes.append((name: "扬声器", route: output))
        case .bluetoothA2DP, .bluetoothHFP:
            routes.append((name: output.portName, route: output))
        case .airPlay:
            routes.append((name: "AirPlay", route: output))
        default:
            routes.append((name: output.portName, route: output))
        }
    }
    return routes
}

2. 自定义按钮触发弹窗

隐藏原MPVolumeView的路由按钮,用自定义按钮替代:

// 创建自定义路由选择按钮
let customRouteButton = UIButton(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
let symbolConfiguration = UIImage.SymbolConfiguration(pointSize: 40, weight: .regular)
let sfSymbol = UIImage(systemName: "airplayvideo.circle.fill", withConfiguration: symbolConfiguration)
customRouteButton.setImage(sfSymbol, for: .normal)
customRouteButton.tintColor = .gray
customRouteButton.addTarget(self, action: #selector(showCustomRoutePicker), for: .touchUpInside)
self.vwMV.addSubview(customRouteButton)

// 隐藏系统默认路由按钮
volumeView.routeButton?.isHidden = true

3. 弹窗显示中文选项并切换路由

@objc func showCustomRoutePicker() {
    let routes = getAvailableAudioRoutes()
    guard !routes.isEmpty else { return }
    
    let alert = UIAlertController(title: "选择音频输出", message: nil, preferredStyle: .actionSheet)
    for route in routes {
        alert.addAction(UIAlertAction(title: route.name, style: .default, handler: { [weak self] _ in
            self?.switchToAudioRoute(route.route)
        }))
    }
    alert.addAction(UIAlertAction(title: "取消", style: .cancel))
    
    // iPad适配(按需添加)
    if let popover = alert.popoverPresentationController {
        popover.sourceView = customRouteButton
        popover.sourceRect = customRouteButton.bounds
    }
    
    present(alert, animated: true)
}

func switchToAudioRoute(_ route: AVAudioSessionPortDescription) {
    do {
        try AVAudioSession.sharedInstance().setPreferredOutputPort(route)
    } catch {
        print("Failed to switch audio route: \(error)")
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 19:17:39