DispatchSource.makeTimerSource当按下后退按钮时崩溃应用程序Swift
我已经实现了使用DispatchSource和计时器工作的录制音频(录制和播放工作正常)的计时器,但是当我按下我的导航控制器选项卡上的后退按钮时,应用程序崩溃。我可以毫无问题地前进到下一个屏幕。 错误:线程1:EXC_BAD_INSTRUCTION(code = EXC_I386_INVOP,subcode = 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 ?? "")
}
}
回答:
这最终被解决我的问题。忽略来自上述两个谁没有解决这个问题的一个心怀不满的向下投票:
var updateTimer: DispatchSourceTimer? @IBOutlet weak var timeLabel: UILabel!
func startTimer() {
let formatter = DateComponentsFormatter()
formatter.zeroFormattingBehavior = .pad
formatter.includesApproximationPhrase = false
formatter.allowedUnits = [.minute, .second]
formatter.calendar = Calendar.current
let queue = DispatchQueue.main
updateTimer = DispatchSource.makeTimerSource(queue: queue)
updateTimer!.schedule(deadline: .now(), repeating: .milliseconds(100))
updateTimer!.setEventHandler { [weak self] in
self?.timeLabel.text = formatter.string(from: AudioRecorderManager.shared.recorder!.currentTime)
}
updateTimer!.resume()
}
func stopTimer() {
updateTimer?.cancel()
updateTimer = nil
}
deinit {
self.stopTimer()
}
@IBAction func toggleRecordButton(_ sender: UIButton) {
if AudioRecorderManager.shared.recorder == nil {
if AudioRecorderManager.shared.recordAudio(fileName: "NewRecording") {
startTimer()
}
}
else {
stopTimer()
AudioRecorderManager.shared.finishRecording()
AudioRecorderManager.shared.recorder = nil
}
}
以上是 DispatchSource.makeTimerSource当按下后退按钮时崩溃应用程序Swift 的全部内容, 来源链接: utcz.com/qa/259210.html