2016-09-11 1 views
0

사용자가 버튼을 누르고 배경색을 변경 (노란색으로)하고 WAV를 재생하고 WAV가 완료되면 버튼이 원래 색상 (빨간색). 따라서 사운드 주변에 완료 핸들러가 있어야합니다. 아래 코드의 다양한 조합을 시도했지만 WAV가 재생되고 단추가 색상을 변경하는 것으로 나타나지 않습니다.스위프트 - 누르기 버튼 (완료 처리기 문제)

잘못된 접근입니까? 아니면 잘못된 것입니까? 완성 된 핸들러를 색상 변경과 관련 지어 놓고 싶지는 않을 것 같습니다. 과장된 생각입니다.

감사합니다.

typealias CompletionHandler = (success:Bool) -> Void 

@IBAction func fireButton(sender: AnyObject) { 
    playLaser({ (success)-> Void in 
     if success { 
      self.shots -= 1 
      self.labelShotsLeft.text = String(self.shots) 
     } else { 

     } 
    }) 
} 

func playLaser(completionHandler: CompletionHandler) { 
    fireButton.layer.backgroundColor = UIColor.yellowColor().CGColor 
    let url = NSBundle.mainBundle().URLForResource("laser", withExtension: "wav")! 
    do { 
     player = try AVAudioPlayer(contentsOfURL: url) 
     guard let player = player else { return } 
     player.prepareToPlay() 
     player.play() 
     } catch let error as NSError { 
      print(error.description) 
    } 
    self.fireButton.layer.backgroundColor = UIColor.redColor().CGColor 
    completionHandler(success: true) 
} 

답변

0

이 조금 더되는 그 질문 중 하나입니다 눈을 맞추기보다 미묘하다. 각 작업 주위에 세 개의 완료 핸들러를 넣으려고했습니다. 색상을 노란색으로 변경하고 소리를 재생하고 색상을 다시 빨간색으로 변경합니다. 코드는 내가 NSLogged 올바른 순서대로 실행되고 있지만 화면의 컨트롤을 업데이트하는 단추가 색을 변경 한 적이 있습니다.

스위프트 2.0

@IBAction func fireButton(sender: AnyObject) { 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { 
     dispatch_sync(dispatch_get_main_queue()) { 
      self.fireButton.layer.backgroundColor = UIColor.yellowColor().CGColor 
     } 
     self.playLaser({ (success)-> Void in 
      if success { 
       self.shots -= 1 
      } else { 
      } 
     }) 
     dispatch_sync(dispatch_get_main_queue()) { 
      self.labelShotsLeft.text = String(self.shots) 
      self.fireButton.layer.backgroundColor = UIColor.redColor().CGColor 
     } 
    } 
} 

func playLaser(completion: (success: Bool) ->()) { 
    let url = NSBundle.mainBundle().URLForResource("laser", withExtension: "wav")! 
    do { 
     player = try AVAudioPlayer(contentsOfURL: url) 
     guard let player = player else { return } 
     player.play() 
     completion(success: true) 
     } catch let error as NSError { 
     completion(success: false) 
    } 
} 

스위프트 3.0

@IBAction func fireButton(_ sender: AnyObject) { 
    let fireQueue = DispatchQueue(label: "queueFirebutton") 
    fireQueue.async { 
     DispatchQueue.main.sync { 
      self.fireButtonDisabled() 
     } 
     DispatchQueue.main.sync { 
      self.playLaser() 
      self.shots -= 1 
      if self.shots <= 0 { 
       self.shots = 0 
      } 
     } 
     DispatchQueue.main.sync { 
      if self.shots < 0 { self.shots = 0} 
      self.labelShotsLeft.text = String(self.shots) 
      sleep(1) 
      self.fireButtonEnabled() 
     } 
    } 
} 

func playLaser() { 
    let url = Bundle.main.url(forResource: "laser", withExtension: "wav")! 
    do { 
     player = try AVAudioPlayer(contentsOf: url) 
     guard let player = player else { return } 
     player.play() 
    } catch { 
    } 
} 
: 여기에 내가 다른 독자들에게 유용한 희망 작동 코드는
0

코드 마술 일시 정지하고 play.play() 말을해서 기다리지 않는다 - 그 끔찍한 것! 따라서 소위 완료 핸들러는 완료 핸들러가 아닙니다. 즉시 실행 - 곧, 당신은 시작 재생됩니다. 오디오 플레이어가 일 때이 끝나는 시점에 관한 정보를 얻는 것에 대한 코드는 아무것도 수행하지 않습니다.

왜냐하면 델리게이트를 구성하고 재생이 끝나면 오디오 플레이어가 방출하는 delegate message을 수신해야합니다.

1

AVAudioPlayer 재생을 완료하려면 AVAudioPlayerDelegate을 사용해야합니다.

당신은 다음과 같이 작성해야 할 수도 있습니다. (당신은 당신의 ViewController의 선언 헤더에 AVAudioPlayerDelegate 준수를 추가해야합니다)

func playLaser(completionHandler: CompletionHandler) { 
    fireButton.layer.backgroundColor = UIColor.yellowColor().CGColor 
    let url = NSBundle.mainBundle().URLForResource("laser", withExtension: "wav")! 
    do { 
     player = try AVAudioPlayer(contentsOfURL: url) 
     guard let player = player else { return } 
     player.delegate = self //<- Sorry, this was missing in my first post 
     player.play() 
    } catch let error as NSError { 
     print(error.description) 
    } 
    audioPlayerCompletionHandler = completionHandler 
} 

var audioPlayerCompletionHandler: CompletionHandler? 
func audioPlayerDidFinishPlaying(player: AVAudioPlayer, successfully flag: Bool) { 
    self.fireButton.layer.backgroundColor = UIColor.redColor().CGColor 
    audioPlayerCompletionHandler?(success: true) 
}