我有一些NSSound对象,我想将它们转换为AVAudioPlayer实例。我有与NSSound对象相关联的文件路径(NSSounds),但原始文件可能不存在。以下是我到目前为止所拥有的:
class SoundObj: NSObject {
var path: NSURL?
var sound: NSSound?
var player: AVAudioPlayer
}
let aSound = SoundObj()
aSound.path = NSURL(fileURLWithPath: "file:///path/to/sound.m4a")
aSound.sound = NSSound(contentsOfURL: aSound.path)!
do {
try aSound.player = AVAudioPlayer(contentsOfURL: aSound.path)
} catch {
// perhaps use AVAudioPlayer(data: ...)?
}如何将NSSound对象转换为AVAudioPlayer实例?
发布于 2016-05-04 00:07:38
因此,我没有看到从NSSound对象获取URL的公共接口,所以我在私有报头中进行了挖掘,看看我能找到什么。结果发现,有私有实例方法url和_url,它们返回NSSound的URL。据推测,这些都是用于NSURL科特迪瓦或属性的获取器。
对于Objective,这很容易:我们只需将这些方法添加到新的接口或扩展中即可。有了纯粹的Swift,事情就更棘手了,我们需要通过一个Objective协议公开访问器:
@objc protocol NSSoundPrivate {
var url: NSURL? { get }
}因为url是一个实例方法,所以使用func url() -> NSURL?可以获得更好的结果,而不是使用变量。您的理解可能会有所不同:使用var来模拟只读属性的行为似乎对我有用。
我在AVAudioPlayer上的一个扩展中编写了一个新的方便初始化器
extension AVAudioPlayer {
convenience init?(sound: NSSound) throws {
let privateSound = unsafeBitCast(sound, NSSoundPrivate.self)
guard let url = privateSound.url else { return nil }
do {
try self.init(contentsOfURL: url)
} catch {
throw error
}
}
}用法:
let url = NSURL(...)
if let sound = NSSound(contentsOfURL: url, byReference: true) {
do {
let player = try AVAudioPlayer(sound: sound)
player?.play()
} catch {
print(error)
}
}在试图在ivars、实例方法和NSSound属性中找到与NSSound相关的任何内容之后,我得出的结论是,用于初始化NSSound的任何数据部分在类的实现中的某个位置都是模糊的,并且无法像NSSound那样可用。
https://stackoverflow.com/questions/36885087
复制相似问题