Reputation: 524
In my class, I have a property that is a sort of audioPlayer and I am planning to do the setup job in a closure as this:
var urlPath = Bundle.main.url(forResource: "Focus", withExtension: "mp3")!
var audioPlayer:AVAudioPlayer = { var player = try! AVAudioPlayer.init(contentsOf: urlPath)
return player }()
Instance member 'urlPath' cannot be used on type 'BackgroundAudio'
I don't quite understand what is wrong with my code? How to resolve this, thanks in advance.
Upvotes: 1
Views: 59
Reputation: 437452
Correct, it's saying that it cannot use the other stored property during initialization, because it doesn't know if it is initialized or not. As The Swift Programming Language says:
If you use a closure to initialize a property, remember that the rest of the instance has not yet been initialized at the point that the closure is executed. This means that you cannot access any other property values from within your closure, even if those properties have default values. You also cannot use the implicit
self
property, or call any of the instance’s methods.
You can resolve this by making audioPlayer a lazy
var, so the initialization is deferred until you first use it, resolving the ambiguity. E.g.
var urlPath = Bundle.main.url(forResource: "Focus", withExtension: "mp3")!
lazy var audioPlayer: AVAudioPlayer = try! AVAudioPlayer(contentsOf: self.urlPath)
Or if you don't need this URL
reference elsewhere, you can just have a single constant:
let audioPlayer: AVAudioPlayer = {
var urlPath = Bundle.main.url(forResource: "Focus", withExtension: "mp3")!
return try! AVAudioPlayer(contentsOf: urlPath)
}()
Lots of options. The key is that you can't have a simple stored property initializing itself using another property's value. You need someway to resolve the ambiguity, such as the two above approaches.
Upvotes: 0
Reputation: 3499
There was a syntax error in your code. As audioPlayer
is a computed property, you should not have =
.
The following
var audioPlayer:AVAudioPlayer = { var player = try! AVAudioPlayer.init(contentsOf: urlPath)
return player }()
should be written as
var audioPlayer: AVAudioPlayer {
var player = try! AVAudioPlayer(contentsOf: urlPath)
return player
}
Upvotes: 0
Reputation: 8322
Try this :
import AudioToolbox
import AVFoundation
let url = Bundle.main.url(forResource: "Focus", withExtension: "mp3")!
do {
player = try AVAudioPlayer(contentsOf: url)
guard let player = player else { return }
player.prepareToPlay()
player.play()
} catch let error as NSError {
print(error.description)
}
Upvotes: 1