Так что я не видел публичный интерфейс, чтобы получить URL-адрес от объекта NSSound
, поэтому я пошел копать через private headers, чтобы увидеть, что я могу найти. Оказывается, существуют частные методы экземпляра url
и _url
, которые возвращают URL-адрес NSSound
. Предположительно, это геттеры для ivar или свойства.
С Objective-C это было бы просто: мы просто добавим методы к новому интерфейсу или расширению. С чисто Swift вещи немного сложнее, и мы должны подвергать аксессор через протокол Objective-C:
@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)
}
}
После попытки найти все, что связано с NSData
в Ивар, методы экземпляра, и свойства NSSound, я пришел к выводу, что часть данных, которую вы используете для инициализации NSSound
, была запутана где-то в реализации класса и недоступна как URL-адрес.
Если звуковой файл не существует, это не приведет к сбою этой строки? 'aSound.sound = NSSound (contentsOfURL: aSound.path)!' – brimstone
Да, но для этого случая '.sound' никогда не имеет значения null. – Matt
Честно говоря, я не думаю, что вы можете получить звуковые данные от NSSound. – brimstone