I have some NSSound
objects that I'd like to convert to AVAudioPlayer
instances. I have file paths (NSURL
s) 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
NSSound
object, so I went digging through the private headers to see what I could find. Turns out there are private instance methodurl
and_url
which return the URL of anNSSound
. Presumably these are getters for anNSURL
ivar 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
url
is an instance method, you may get better results withfunc url() -> NSURL?
instead of using a variable. Your milage may vary: using avar
to 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
NSData
in 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 anNSSound
is obfuscated somewhere in the implementation of the class, and is not available like the URL is.