В моем приложении есть таймер, который обновляет текущее время в пользовательском интерфейсе и сверяет заданное время для запуска события. Однако мое приложение вылетает, когда срабатывает таймер. Журналы сбоев указывают на ViewController.TimeUp() и замыкание №1 в ViewController.updateTimer(). Вот упрощенная версия трассировки стека и связанного с ней кода:
Код: Выделить всё
Crashed: com.apple.main-thread 0 EarAlarm 0x3677c AlarmViewController.TimeUp() + 4375193468 (:4375193468) 1 EarAlarm 0x297e8 closure #1 in AlarmViewController.updateCurrentTime() + 971 (AlarmViewController.swift:971) 2 EarAlarm 0x4dd98 thunk for @escaping @callee_guaranteed () -> () + 4375289240 (:4375289240) 3 libdispatch.dylib 0x26a8 + 32 4 libdispatch.dylib 0x4300 + 20 5 libdispatch.dylib 0x12998 + 984 6 libdispatch.dylib 0x125b0 _dispatch_main_queue_callback_4CF + 44 7 CoreFoundation 0x36f9c + 16 8 CoreFoundation 0x33ca8 + 1996 9 CoreFoundation 0x333f8 CFRunLoopRunSpecific + 608 10 GraphicsServices 0x34f8 GSEventRunModal + 164 11 UIKitCore 0x22c8a0 + 888 12 UIKitCore 0x22bedc UIApplicationMain + 340 13 EarAlarm 0x40bfc main + 22 (AppDelegate.swift:22) 14 ??? 0x1aec46dcc (シンボルが不足しています)
`import UIKit
импорт AVFoundation
импорт MediaPlayer
импорт AudioToolbox
импорт UserNotifications
импортировать FirebaseCore
импортировать GoogleMobileAds
импортировать FirebaseAnalytics
класс AlarmViewController: UIViewController, UNUserNotificationCenterDelegate {
Код: Выделить всё
let userDefaults = UserDefaults.standard
var appDelegate:AppDelegate = UIApplication.shared.delegate as! AppDelegate
@IBOutlet weak var bannerView: GADBannerView!
@IBOutlet weak var bannerViewBig: GADBannerView!
var heightConstraint : NSLayoutConstraint?
var MPplayer: MPMusicPlayerController!
var MPplayerState: MPMusicPlaybackState!
var displayTimer: Timer?
var timer: Timer?
var snoozeTimer: Timer?
var vibrationTimer: Timer?
var SlowlyVolumeTimer: Timer?
var AudioPlayerSlowlyVolumeTimer: Timer?
var currentTime: String?
var df = DateFormatter()
var hourFormat = DateFormatter()
var minuteFormat = DateFormatter()
var nowHourStr : String?
var nowMinuteStr : String?
var nowHourInt : Int?
var nowMinuteInt : Int?
var setHour : Int?
var setMinute : Int?
var residueTime : Int?
var residueSeconds : Int?
let audioSession = AVAudioSession.sharedInstance()
var mpVolumeSlider = UISlider()
var SaveUserVolume : Float!
var MPplayerPlayingInt : Int!
var longPressTimer: Timer?
var slowlyInt : Int!
var slowlyFlo : Float!
var CurrentVolumeFlo : Float!
var SavedVolumeFlo : Float!
var CurrentSaveFlo : Float!
var SlowlyVolumeChangeFlo : Float!
var audioPlayeSlowlyVolumeChangeFlo : Float!
var audioPlayer:AVAudioPlayer!
var IntroductionPlayer:AVAudioPlayer!
var iPodSongTitle : String? = nil
var iPodUrl : NSURL? = nil
var SongTitle : String? = nil
var snoozeInt : Int!
var snoozeSetTimeSec : Int!
var snoozeTimeSec : Int!
var snoozeDisplaySec : Int!
var snoozeDisplayMin : Int!
var vibrationCount = 5
var introductionStopTimeSecInt : Int!
var nowIntroductionStopTimeSecInt : Int!
var notificationContent = UNMutableNotificationContent()
var alreadyTimeUp : Bool!
var AlarmTitleKey: String!
var iPodAlarmTitleKey: String!
var UseiPodKey: String!
var AlarmVolumeKey: String!
var iPodAlarmURLKey: String!
var slowlyKey: String!
var SnoozeKey: String!
var VibKey: String!
var IntroductionTitleKey: String!
var iPodIntroductionTitleKey: String!
var IntroductionUseiPodKey: String!
var IntroductionVolumeKey: String!
var IntroductionStopTimeKey: String!
var iPodIntroductionURLKey: String!
var iPodIntroductionAlbumArtDataKey: String!
@IBOutlet var NowTimeLabel: UILabel!
@IBOutlet var SetTimeLabel: UILabel!
@IBOutlet var niAlarmLabel: UILabel!
@IBOutlet var systemVolumeLabel: UILabel!
@IBOutlet var volumeParentView: UIView!
@IBOutlet var slider: UISlider!
@IBOutlet weak var UpMainVolumeBtn: UIButton!
@IBOutlet weak var DownMainVolumeBtn: UIButton!
@IBOutlet var SnoozeButton: UIButton!
@IBOutlet var HaikeiImageView: UIImageView!
@IBOutlet weak var nativeAdPlaceholder: UIView!
override func viewDidLoad() {
super.viewDidLoad()
setupVolumeSlider()
do {
try audioSession.setActive(true)
} catch {
do {
try audioSession.setActive(true)
} catch {
do {
try audioSession.setActive(true)
} catch {
do {
try audioSession.setActive(true)
} catch {
do {
try audioSession.setActive(true)
} catch {
do {
try audioSession.setActive(true)
} catch {
do {
try audioSession.setActive(true)
} catch {
do {
try audioSession.setActive(true)
} catch {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {//1秒後に処理する
//ここに処理
do {
try self.audioSession.setActive(true)
} catch {
print("audioSession ラストエラー")
self.dismiss(animated: true, completion: nil)
}
}
}
}
}
}
}
}
}
}
let KillNotificationCenter = NotificationCenter.default
KillNotificationCenter.addObserver(
self,
selector: #selector(SyuuryouKeikoku),
name:UIApplication.willTerminateNotification,
object: nil)
SnoozeButton.isHidden = true
SnoozeButton.isEnabled = false
niAlarmLabel.text = ""
setTimer()
let longPress5Up = UILongPressGestureRecognizer(target: self, action: #selector(self.longPressUpMainVolume(gesture:)))
longPress5Up.minimumPressDuration = 0.3
UpMainVolumeBtn.addGestureRecognizer(longPress5Up)
let longPress1Up = UILongPressGestureRecognizer(target: self, action: #selector(self.longPressDownMainVolume(gesture:)))
longPress1Up.minimumPressDuration = 0.3
DownMainVolumeBtn.addGestureRecognizer(longPress1Up)
nativeAdPlaceholder.alpha = 0
prepareIntroductionMuonAudioPlayer()
IntroductionPlayer.play()
admob()
admobBig()
}
func getFileURL(fileName: String) -> URL {
let docDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
return docDir.appendingPathComponent(fileName)
}
func setTimer() {
setHour = appDelegate.SettingAlarmTimeHour
setMinute = appDelegate.SettingAlarmTimeMiunte
SetTimeLabel.text = "\(String(format: "%02d", setHour!)) : \(String(format: "%02d", setMinute!))"
self.userDefaults.set(appDelegate.AlarmNumber, forKey: "savedAlarmNumber")
self.userDefaults.set(setHour, forKey: "savedAlarmHourInsurance")
self.userDefaults.set(setMinute, forKey: "savedAlarmMinuteInsurance")
nowIntroductionStopTimeSecInt = 0
introductionStopTimeSecInt = userDefaults.integer(forKey: IntroductionStopTimeKey)
self.timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateCurrentTime), userInfo: nil, repeats: true)
displayNowTime()
displayTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateNowTimeLabel), userInfo: nil, repeats: true)
AtoHowManyMinutesLater()
if residueTime! > 1434
{
} else
{
setTrigger()
}
}
@objc private func updateCurrentTime(){
df.locale = Locale(identifier: "en_US_POSIX")
hourFormat.locale = Locale(identifier: "en_US_POSIX")
minuteFormat.locale = Locale(identifier: "en_US_POSIX")
df.dateFormat = "HH:mm:ss"
hourFormat.dateFormat = "HH"
minuteFormat.dateFormat = "mm"
df.timeZone = TimeZone.current
hourFormat.timeZone = TimeZone.current
minuteFormat.timeZone = TimeZone.current
let timezoneDate = df.string(from: Date())
let timezoneDateH = hourFormat.string(from: Date())
let timezoneDateM = minuteFormat.string(from: Date())
currentTime = timezoneDate
nowHourStr = timezoneDateH
nowMinuteStr = timezoneDateM
nowHourInt = Int(nowHourStr!)
nowMinuteInt = Int(nowMinuteStr!)
NowTimeLabel.text = currentTime
AtoHowManyMinutesLater()
nowIntroductionStopTimeSecInt = nowIntroductionStopTimeSecInt + 1
if nowIntroductionStopTimeSecInt == introductionStopTimeSecInt {
IntroductionPlayer.volume = 0
}
if(nowHourInt == setHour && nowMinuteInt == setMinute){
if timer!.isValid {
timer?.invalidate()
}
if alreadyTimeUp == true {
} else {
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
self.TimeUp()
}
}
}
}
func AtoHowManyMinutesLater(){
var residueTimeHour = 0
var residueTimeMinute = 0
let setAlarmMinute = setHour! * 60 + setMinute!
let nowTimeMinute = nowHourInt! * 60 + nowMinuteInt!
residueTime = setAlarmMinute - nowTimeMinute
if residueTime! > 0
{
if residueTime! < 60
{
residueTimeMinute = residueTime!
} else if residueTime! >= 60
{
residueTimeHour = residueTime! / 60
residueTimeMinute = residueTime! % 60
}
} else if residueTime! < 0
{
residueTime = setAlarmMinute + 1440 - nowTimeMinute
if residueTime! < 60
{
} else if residueTime! >= 60
{
residueTimeHour = residueTime! / 60
residueTimeMinute = residueTime! % 60
}
}
let hourSt = NSLocalizedString("時間", comment: "")
let minutesSt = NSLocalizedString("分", comment: "")
let goSt = NSLocalizedString("後", comment: "")
if residueTimeHour 1
{
niAlarmLabel.text = "\(residueTimeMinute)\(minutesSt)\(goSt)"//分後
} else if residueTimeMinute 0
{
niAlarmLabel.text = "\(residueTimeHour)\(hourSt)\(residueTimeMinute)\(minutesSt)\(goSt)"//時間 分後
}
}
@objc private func updateNowTimeLabel(){
displayNowTime()
}
func displayNowTime() {
df.locale = Locale(identifier: "en_US_POSIX")
hourFormat.locale = Locale(identifier: "en_US_POSIX")
minuteFormat.locale = Locale(identifier: "en_US_POSIX")
df.dateFormat = "HH:mm:ss"
hourFormat.dateFormat = "HH"
minuteFormat.dateFormat = "mm"
df.timeZone = TimeZone.current
hourFormat.timeZone = TimeZone.current
minuteFormat.timeZone = TimeZone.current
let timezoneDate = df.string(from: Date())
let timezoneDateH = hourFormat.string(from: Date())
let timezoneDateM = minuteFormat.string(from: Date())
currentTime = timezoneDate
NowTimeLabel.text = currentTime
nowHourStr = timezoneDateH
nowMinuteStr = timezoneDateM
nowHourInt = Int(nowHourStr!)
nowMinuteInt = Int(nowMinuteStr!)
}
func TimeUp() {
if Thread.isMainThread {
print("MainThreadです TimeUp")
} else {
print("MainThreadではない TimeUp")
}
alreadyTimeUp = true
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
UNUserNotificationCenter.current().removeAllDeliveredNotifications()
niAlarmLabel.text = ""
if IntroductionPlayer == nil {
} else {
if(IntroductionPlayer.isPlaying) {
IntroductionPlayer.stop()
}
}
prepareAudioPlayer()
SaveUserVolume = mpVolumeSlider.value
let useiPod = userDefaults.integer(forKey: UseiPodKey)
if useiPod == 2 {
} else {
MPplayer = MPMusicPlayerController.systemMusicPlayer
MPplayerState = MPplayer.playbackState
if MPplayerState == MPMusicPlaybackState.playing{
MPplayer.pause()
MPplayerPlayingInt = 1
}
if AVAudioSession.sharedInstance().isOtherAudioPlaying {
}
}
let AlarmVolumeFlo = userDefaults.float(forKey: AlarmVolumeKey)
slowlyInt = userDefaults.integer(forKey: slowlyKey)
audioPlayer.volume = 0
if slowlyInt == 0 {
audioPlayer.volume = 1
mpVolumeSlider.value = AlarmVolumeFlo
slider?.value = self.mpVolumeSlider.value
} else {
slowlyFlo = Float(slowlyInt)
audioPlayeSlowlyVolumeChangeFlo = 0
if AlarmVolumeFlo > SaveUserVolume{
CurrentVolumeFlo = SaveUserVolume
SavedVolumeFlo = AlarmVolumeFlo
CurrentSaveFlo = SavedVolumeFlo - CurrentVolumeFlo
SlowlyVolumeChangeFlo = CurrentVolumeFlo
SlowlyVolumeTimer = Timer.scheduledTimer(timeInterval: 0.2, target: self, selector: #selector(SlowlyVolume), userInfo: nil, repeats: true)
} else {
mpVolumeSlider.value = AlarmVolumeFlo
slider?.value = self.mpVolumeSlider.value
}
AudioPlayerSlowlyVolumeTimer = Timer.scheduledTimer(timeInterval: 0.2, target: self, selector: #selector(AudioPlayerSlowlyVolume), userInfo: nil, repeats: true)
}
audioPlayer.play()
let vibInt = userDefaults.integer(forKey: VibKey)
if vibInt == 0 {
vibrationTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(VibrationTimerAction), userInfo: nil, repeats: true)
}
push()
snoozeSwitch()
}
Источник: https://stackoverflow.com/questions/781 ... etimer-cau