在我的应用程序中,我有2个UIButtons,每个按钮播放2个声音(播放一个声音,暂停,播放另一个声音),每次按下UIButtons图像时,我的应用程序也有一些标签。问题就是当我按下一个UIButton(需要大约4秒才能播放和完成声音)时我无法按下另一个按钮,甚至在标签之间切换,应用程序冻结,直到UI按钮的动作完成,然后我可以按其他按钮或切换标签。 这是我的代码:
import UIKit
import AVFoundation
import CoreData
class FirstViewController: UIViewController {
var player:AVAudioPlayer = AVAudioPlayer()
var player2:AVAudioPlayer = AVAudioPlayer()
@IBAction func play(_ sender: Any) {
player.play()
sleep(1)
player2.play()
}
@IBAction func play2(_ sender: Any) {
player.play()
sleep(1)
player2.play()
}
@IBOutlet weak var play: UIButton!
@IBOutlet weak var play2: UIButton!
var buttonActive = false
@IBAction func pPressed(_ sender: Any) {
if buttonActive {
play.setBackgroundImage(UIImage(named: "SwitchD-Icon-40"), for: .normal)
} else {
play.setBackgroundImage(UIImage(named: "Switch-Icon-40"), for: .normal)
}
buttonActive = !buttonActive
}
@IBAction func p2Pressed(_ sender: Any) {
if buttonActive {
play2.setBackgroundImage(UIImage(named: "SwitchD-Icon-40"), for: .normal)
} else {
play2.setBackgroundImage(UIImage(named: "Switch-Icon-40"), for: .normal)
}
buttonActive = !buttonActive
}
override func viewDidLoad() {
super.viewDidLoad()
play.setBackgroundImage(UIImage(named: "SwitchD-Icon-40"), for: .normal)
play2.setBackgroundImage(UIImage(named: "SwitchD-Icon-40"), for: .normal)
do
{
let audioPath = Bundle.main.path(forResource: "DTMF-1", ofType: "mp3")
try player = AVAudioPlayer(contentsOf: NSURL(fileURLWithPath: audioPath!) as URL)
let audioPath2 = Bundle.main.path(forResource: "DTMF-2", ofType: "mp3")
try player2 = AVAudioPlayer(contentsOf: NSURL(fileURLWithPath: audioPath2!) as URL)
}
有没有办法让我的应用更快?
答案 0 :(得分:0)
实施做某事,暂停并做其他事情的一种着名方法是使用Timer
。
以下代码还包括:
AVAudioPlayer
Timer
无效stop
AVAudioPlayer
何时可以重新使用请尝试:
class FirstViewController: UIViewController {
var player: AVAudioPlayer? //### You should not instantiate unused objects
var player2: AVAudioPlayer?
var secondSoundTimer: Timer?
private func startPlaying() {
stopPlaying()
player?.play()
//### Using `Timer` is one way to achieve pause-like thing.
//### If you need to target older iOSs than 10.0, you need to modify this part.
secondSoundTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false) {timer in
self.player2?.play()
self.secondSoundTimer?.invalidate()
self.secondSoundTimer = nil
}
}
private func stopPlaying() {
secondSoundTimer?.invalidate()
secondSoundTimer = nil
if let player = player, player.isPlaying {
//### Stop playing (keeping internal `prepared` state) and rewind to the first place.
player.pause()
player.currentTime = 0
}
if let player2 = player2, player2.isPlaying {
player2.pause()
player2.currentTime = 0
}
}
@IBOutlet weak var play: UIButton!
@IBOutlet weak var play2: UIButton!
var buttonActive = false
@IBAction func pPressed(_ sender: Any) {
startPlaying()
if buttonActive {
play.setBackgroundImage(UIImage(named: "SwitchD-Icon-40"), for: .normal)
} else {
play.setBackgroundImage(UIImage(named: "Switch-Icon-40"), for: .normal)
}
buttonActive = !buttonActive
}
//### Don't you need `button2Active`?
@IBAction func p2Pressed(_ sender: Any) {
startPlaying()
if buttonActive {
play2.setBackgroundImage(UIImage(named: "SwitchD-Icon-40"), for: .normal)
} else {
play2.setBackgroundImage(UIImage(named: "Switch-Icon-40"), for: .normal)
}
buttonActive = !buttonActive
}
override func viewDidLoad() {
super.viewDidLoad()
play.setBackgroundImage(UIImage(named: "SwitchD-Icon-40"), for: .normal)
play2.setBackgroundImage(UIImage(named: "SwitchD-Icon-40"), for: .normal)
do {
//### You can get URL directly from Bundle
//### It's better to apply forced-unwrapping as soon as possible, if you need it eventually.
let audioURL = Bundle.main.url(forResource: "DTMF-1", withExtension: "mp3")!
player = try AVAudioPlayer(contentsOf: audioURL)
//### `prepareToPlay()` improves response for the first play.
player?.prepareToPlay()
let audioURL2 = Bundle.main.url(forResource: "DTMF-2", withExtension: "mp3")!
player2 = try AVAudioPlayer(contentsOf: audioURL2)
player2?.prepareToPlay()
} catch {
print(error)
//... or any other things you need...
}
//...
}
//### Stop playing on transition to other ViewConrollers.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
stopPlaying()
}
}