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

iOS应用中播放UNNotificationSound.default()及获取播放用户选择铃声的方法

嘿,我来帮你搞定这两个iOS音频相关的问题~这两个场景在很多社交、工具类APP里都很常见,我给你详细拆解一下具体实现方式:

一、如何在iOS应用内播放UNNotificationSound.default()?

UNNotificationSound的默认音效本质是系统自带的通知提示音,但它本身是为推送通知设计的,要在应用内直接播放,得先拿到它对应的音频文件URL,再用AVAudioPlayer或者AVPlayer来实现播放。这里给你用AVAudioPlayer的完整实现:

  1. 先配置音频权限
    别忘了在Info.plist里添加NSAudioUsageDescription键,写上应用使用音频的原因(比如“用于播放通知提示音”),不然会触发权限错误甚至崩溃。

  2. 获取默认音效的URL并播放
    代码示例(Swift):

    import AVFoundation
    import UserNotifications
    
    func playDefaultNotificationSound() {
        // 配置音频会话,确保应用可以正常播放音频
        do {
            try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
            try AVAudioSession.sharedInstance().activate(options: [.notifyOthersOnDeactivation])
        } catch {
            print("音频会话配置失败: \(error.localizedDescription)")
            return
        }
    
        // 获取默认通知音效的URL
        guard let soundURL = UNNotificationSound.default().soundURL else {
            print("无法获取默认通知音效的URL")
            return
        }
    
        // 初始化播放器并播放
        do {
            let player = try AVAudioPlayer(contentsOf: soundURL)
            player.prepareToPlay() // 提前加载音频,优化播放响应速度
            player.play()
        } catch {
            print("播放器初始化失败: \(error.localizedDescription)")
        }
    }
    

    如果你需要更灵活的播放控制(比如暂停、进度条),也可以用AVPlayer替代,用法类似,只是初始化方式改成AVPlayer(url: soundURL)后调用play()即可。

二、获取系统铃声列表并实现播放/获取文件名

要做一个包含系统默认铃声的选择列表,你需要访问系统的音频资源目录,枚举其中的音频文件,再对选中的铃声做播放或文件名提取操作:

1. 先定义一个铃声模型(可选但推荐)

用一个简单的结构体来统一管理铃声的名称和URL,方便后续列表展示和操作:

struct Ringtone {
    let displayName: String // 给用户看的铃声名称(去掉后缀)
    let fileURL: URL        // 铃声文件的本地路径
}

2. 枚举系统铃声目录,获取完整列表

系统铃声主要存在两个目录:通知铃声在/System/Library/Audio/UISounds/Notifications/,电话铃声在/System/Library/Audio/UISounds/Ringtones/。你可以根据需求选择枚举哪个目录:

import AVFoundation

func fetchSystemRingtones() -> [Ringtone] {
    var ringtoneList = [Ringtone]()
    let supportedAudioExtensions = ["caf", "mp3", "m4a"] // iOS支持的音频格式

    // 枚举指定目录下的音频文件
    func scanRingtoneDirectory(at directoryURL: URL) {
        do {
            // 获取目录下所有可见文件
            let fileURLs = try FileManager.default.contentsOfDirectory(
                at: directoryURL,
                includingPropertiesForKeys: nil,
                options: .skipsHiddenFiles
            )

            for fileURL in fileURLs {
                // 过滤出支持的音频格式文件
                guard let fileExt = fileURL.pathExtension.lowercased(), supportedAudioExtensions.contains(fileExt) else {
                    continue
                }
                // 提取去掉后缀的文件名作为显示名称
                let displayName = fileURL.deletingPathExtension().lastPathComponent
                ringtoneList.append(Ringtone(displayName: displayName, fileURL: fileURL))
            }
        } catch {
            print("扫描铃声目录失败: \(error.localizedDescription)")
        }
    }

    // 扫描通知铃声和电话铃声目录
    let notificationDirURL = URL(fileURLWithPath: "/System/Library/Audio/UISounds/Notifications/")
    let ringtoneDirURL = URL(fileURLWithPath: "/System/Library/Audio/UISounds/Ringtones/")
    scanRingtoneDirectory(at: notificationDirURL)
    scanRingtoneDirectory(at: ringtoneDirURL)

    return ringtoneList
}

3. 播放用户选中的铃声

当用户从列表中选中某个铃声后,直接用AVAudioPlayer播放即可,逻辑和播放默认音效一致:

func playSelectedRingtone(_ ringtone: Ringtone) {
    do {
        try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
        try AVAudioSession.sharedInstance().activate()

        let player = try AVAudioPlayer(contentsOf: ringtone.fileURL)
        player.prepareToPlay()
        player.play()
    } catch {
        print("播放选中铃声失败: \(error.localizedDescription)")
    }
}

4. 获取选中铃声的文件名

  • 如果你要不带后缀的显示名称,直接取ringtone.displayName即可;
  • 如果你要带后缀的完整文件名,可以用ringtone.fileURL.lastPathComponent。

注意事项:

  • iOS系统版本更新可能会微调铃声目录结构,建议在不同版本的设备上测试兼容性;
  • 所有系统铃声的播放都是符合Apple开发者规范的,不用担心版权问题;
  • 同样要确保Info.plist中配置了NSAudioUsageDescription权限描述。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:48:08