-2
DispatchSource를 사용하여 녹음 된 오디오 (녹음 및 재생이 잘 작동 함) 타이머를 구현했으며 타이머가 작동하지만 내 탐색 컨트롤러 탭에서 뒤로 버튼을 누르면 앱이 다운됩니다. 아무런 문제없이 다음 화면으로 넘어갈 수 있습니다. 오류 : 스레드 1 : EXC_BAD_INSTRUCTION (코드 = EXC_I386_INVOP, 서브 코드 = 0x0)뒤로 버튼을 누르면 DispatchSource.makeTimerSource가 응용 프로그램을 중단합니다. Swift
누군가가이 이유에 대한 힌트를 제공해 줄 수 있습니까?
내보기 컨트롤러 코드 :
import Foundation
import UIKit
import AVFoundation
class RecordGreetingController: UIViewController {
@IBOutlet weak var timeLabel: UILabel!
var audioPlayer: AVAudioPlayer!
var updateTimer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.main)
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func toggleRecordButton(_ sender: UIButton) {
if AudioRecorderManager.shared.recorder == nil {
if AudioRecorderManager.shared.recordAudio(fileName: "NewRecording") {
updateTimer.resume()
}
let formatter = DateComponentsFormatter()
formatter.zeroFormattingBehavior = .pad
formatter.includesApproximationPhrase = false
formatter.allowedUnits = [.minute, .second]
formatter.calendar = Calendar.current
updateTimer.schedule(deadline: DispatchTime.now(), repeating: DispatchTimeInterval.milliseconds(100))
updateTimer.setEventHandler { [weak self] in
self?.timeLabel.text = formatter.string(from: AudioRecorderManager.shared.recorder!.currentTime)
}
}
else {
AudioRecorderManager.shared.finishRecording()
AudioRecorderManager.shared.recorder = nil
updateTimer.suspend()
}
}
}
내 AudioRecorderManager 클래스 :
import Foundation
import AVFoundation
class AudioRecorderManager: NSObject, AVAudioRecorderDelegate {
static let shared = AudioRecorderManager()
var recordingSession: AVAudioSession!
var recorder: AVAudioRecorder?
func setup() {
recordingSession = AVAudioSession.sharedInstance()
do {
try recordingSession.setCategory(AVAudioSessionCategoryPlayAndRecord, with: .defaultToSpeaker)
try recordingSession.setActive(true)
// Request permission from user
recordingSession.requestRecordPermission{ (allowed) in
if allowed {
print("Mic authorised")
}
else {
print("Mic not authorised")
// TODO display alert to allow microphone access in settings to operate
}
}
}
catch {
print("Failed to set category", error.localizedDescription)
}
}
var meterTimer: Timer?
var recorderApc0: Float? = 0
var recorderPeak0: Float? = 0
// Starts the recording session
func recordAudio(fileName:String) -> Bool {
let url = getUserPath().appendingPathComponent(fileName+".m4a")
let audioURL = URL.init(fileURLWithPath: url.path)
let recordSettings: [String: Any] = [
AVFormatIDKey: NSNumber(value: kAudioFormatAppleLossless),
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue,
AVEncoderBitRateKey: 12000.0,
AVNumberOfChannelsKey: 1,
AVSampleRateKey: 44100.0
]
do {
recorder = try AVAudioRecorder(url: audioURL, settings: recordSettings)
recorder?.delegate = self
recorder?.isMeteringEnabled = true
recorder?.prepareToRecord()
recorder?.record()
self.meterTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { (timer: Timer) in
// Update recorder meter values
if let recorder = self.recorder {
recorder.updateMeters()
self.recorderApc0 = recorder.averagePower(forChannel: 0)
self.recorderPeak0 = recorder.peakPower(forChannel: 0)
}
})
print("Recording")
return true
}
catch {
print("Error recording")
return false
}
}
// Stop recording
func finishRecording() {
self.recorder?.stop()
self.meterTimer?.invalidate()
}
// Gets path for the folder the file is being saved to
func getUserPath() -> URL {
return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
}
func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
print("Audio Manager did finish recording", flag)
}
func audioRecorderEncodeErrorDidOccur(_ recorder: AVAudioRecorder, error: Error?) {
print("Error encoding ", error?.localizedDescription ?? "")
}
}
는 관련없는,하지만 그것을 수행하기 어렵다 동안 전에 타이머를 재개 할 수있는 실행 경로가처럼, 그것은 본다 핸들러와 스케줄을 설정하십시오 ... – Rob
안녕하세요 Rob, 명확히하기 위해 toggleRecordButton IBAction 블록의 시작 부분에 updateTimer.resume()이 있습니다. 처리기와 일정 전에 타이머를 다시 시작하는 것이 잘못된 것이라고 제안 하시겠습니까? – elarcoiris
예, 타이머를 시작하기 전에 타이머를 구성해야한다고 제안합니다. 구성을 완료하기 전에 시작하면 무엇을 기대합니까? 운이 좋다면 아무 것도 잘못 될 것이지만 왜이 문서화되지 않은 행동에 의존하고 있습니까? 시작하기 전에 설정을 완료하는 것이 가장 안전합니다. – Rob