当我在 X 轴上移动 iPhone 时(我正在使用 CoreMotion
和 AVAudioPlayer
),我试图播放短声音(1 到 4 秒)。我想为每个运动方向变化播放一种声音。
我写了下面的代码,但是当我移动 iPhone 时,声音播放了很多次,但移动方向没有改变。下面的 print
调用显示了许多 Down
和 Up
,例如 Down Down Down Up Down Down Up Up...
.如果我评论两个 play
回调,print
会显示我期望的交替:Down Up Down Up Down Up...
。
为什么AVAudioPlayer.play
在移动方向改变时被多次调用?
override func viewDidLoad() {
super.viewDidLoad()
// Audio
audioURL = NSBundle.mainBundle().URLForResource("shortSound", withExtension: "wav")!
do {
try audioPlayer = AVAudioPlayer(contentsOfURL: audioURL)
audioPlayer.prepareToPlay()
} catch {
print("audioPlayer failure")
}
// Sensor
lastDirection = 0
threshold = 2.1
motionManager = CMMotionManager()
if motionManager.accelerometerAvailable {
let queue = NSOperationQueue()
motionManager.startAccelerometerUpdatesToQueue(queue, withHandler: {
data, error in
guard let data = data else{
return
}
// Get the acceleration
let xAccel = data.acceleration.x
let xPositive = xAccel > 0
// Run if the acceleration is higher than theshold
if abs(xAccel) > self.threshold {
// Run only if the direction is changed
if self.lastDirection != 1 && xPositive {
print("Up")
self.play()
self.lastDirection = 1
} else if self.lastDirection != -1 && !xPositive {
print("Down")
self.play()
self.lastDirection = -1
}
}
})
}
}
func play() {
audioPlayer.currentTime = 0
audioPlayer.play()
}
最佳答案
您可能遇到线程问题。您在后台队列(queue
,一个任意的 NSOperationQueue,顺便说一句,您也未能保留)上运行更新,但随后您正在与 self.lastDirection
并在同一个后台队列上调用 self.play()
,而不考虑这些事件的线程安全性。
我建议至少重写此部分:
if self.lastDirection != 1 && xPositive {
print("Up")
self.play()
self.lastDirection = 1
} else if self.lastDirection != -1 && !xPositive {
print("Down")
self.play()
self.lastDirection = -1
}
...更像这样:
dispatch_async(dispatch_get_main_queue()) {
if self.lastDirection != 1 && xPositive {
self.lastDirection = 1
print("Up")
self.play()
} else if self.lastDirection != -1 && !xPositive {
self.lastDirection = -1
print("Down")
self.play()
}
}
请注意,我做了两处更改:我已经跳转到主线程进行整个 check-print-play-toggle 舞蹈,并且我颠倒了事件的顺序以便它进入 check-toggle-打印播放。
此外,我还建议进行另外两项更改:保留操作队列(即使其成为属性而不是本地属性),并降低运动管理器更新的频率(通过设置较低的 accelerometerUpdateInterval
)。
关于ios - 如何在 iOS 中使用 CoreMotion 和 AVAudioPlayer 播放短音频文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34597669/