I have some NSSound objects that I'd like to convert to AVAudioPlayer instances. I have file paths (NSURLs) associated with the NSSound objects, but the original file may not exist. Here is what I have so far:
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: ...)?
}
How do I convert an NSSound object to an AVAudioPlayer instance?
So I didn't see a public interface to get the URL from an
NSSoundobject, so I went digging through the private headers to see what I could find. Turns out there are private instance methodurland_urlwhich return the URL of anNSSound. Presumably these are getters for anNSURLivar or property.With Objective-C this would be easy: we would just add the methods to a new interface or extension. With pure Swift things are a little trickier, and we need to expose the accessor via an Objective-C protocol:
Since
urlis an instance method, you may get better results withfunc url() -> NSURL?instead of using a variable. Your milage may vary: using avarto emulate the behavior of a read-only property seemed to work for me.I wrote a new convenience initializer in an extension on
AVAudioPlayer:Usage:
After attempting to find anything related to
NSDatain the ivars, instance methods, and properties of an NSSound, I have come to the conclusion that the data portion of whatever you use to initialize anNSSoundis obfuscated somewhere in the implementation of the class, and is not available like the URL is.