Reputation: 312
I'm getting an error when I run a certain type of code in my macOS project and I'm not sure how to fix it. Here's the error I'm getting:
This is the code that's giving me the error:
func AlarmAlertBox() {
let alert = NSAlert()
alert.messageText = AlarmTitleVar
alert.informativeText = DescriptionVar
alert.addButton(withTitle: "OK")
let result = alert.runModal()
switch(result) {
case NSAlertFirstButtonReturn:
print("OK", terminator: "")
default:
break
}
}
EDIT (was requested to add this): I am running this code in a Timer function:
_ = DispatchQueue.global().async {
var ReminderNum = 1
self.ReminderCheckON = true
while self.ReminderCheckON == true {
let int : Int = ReminderNum
let ReminderStr = String(int)
let ReminderStuff = UserDefaults().string(forKey: ReminderStr) ?? ""
ReminderNum = ReminderNum + 1
if ReminderStuff == "" {
self.ReminderCheckON = false
ReminderNum = 1
}
if ReminderStuff.range(of: self.ReminderCurrentTime.stringValue) != nil
{
print("Alarm Time!")
if self.DeleteAlarm == "ON" {
UserDefaults().set("-", forKey: ReminderStr)
self.AlarmsEnd()
self.UpcomingAlarms.stringValue = ""
self.ReminderList.removeAllItems()
self.AlarmsCheck()
}
self.AlarmTitleVar = UserDefaults().string(forKey: "T" + ReminderStr) ?? ""
self.DescriptionVar = UserDefaults().string(forKey: "D" + ReminderStr) ?? ""
self.ReminderCheckON = false
self.ReminderRingToneVar = UserDefaults().string(forKey: "R" + ReminderStr) ?? "Alarm"
if self.ReminderRingToneVar == "Spring" {
let Spring = NSSound(named: "Spring")
Spring!.play()
self.AlarmAlertBox()
Spring!.stop()
}
if self.ReminderRingToneVar == "Alarm" {
let Alarm = NSSound(named: "RingDing")
Alarm!.play()
self.AlarmAlertBox()
Alarm!.stop()
}
if self.ReminderRingToneVar == "Strings" {
let Strings = NSSound(named: "Strings")
Strings!.play()
self.AlarmAlertBox()
Strings!.stop()
}
if self.ReminderRingToneVar == "Happy" {
let Happy = NSSound(named: "Happy")
Happy!.play()
self.AlarmAlertBox()
Happy!.stop()
}
if self.ReminderRingToneVar == "Bouncy" {
let Bouncy = NSSound(named: "Joshua's Creation")
Bouncy!.play()
self.AlarmAlertBox()
Bouncy!.stop()
}
if self.ReminderRingToneVar == "Star-Spangled Banner" {
let StarSpangledBanner = NSSound(named: "The_United_States_Army_Old_Guard_Fife_and_Drum_Corps_-_02_-_United_States_National_Anthem_The_Star_Spangled_Banner")
StarSpangledBanner!.play()
self.AlarmAlertBox()
StarSpangledBanner!.stop()
}
}
}
}
The debug window is giving me this:
2016-09-27 13:35:00.856685 Clock Pro[2441:115266] [General] An uncaught exception was raised
2016-09-27 13:35:00.856732 Clock Pro[2441:115266] [General] 2016-09-27 13:35:00.856803 Clock Pro[2441:115266] [General] 2016-09-27 13:35:00.856885 Clock Pro[2441:115266] * Terminating app due to uncaught exception 'NSGenericException', reason: '-[NSAlert runModal] may only be invoked from the main thread. Behavior on other threads is undefined.' * First throw call stack: ( 0 CoreFoundation 0x00007fffaaefd52b exceptionPreprocess + 171 1 libobjc.A.dylib 0x00007fffbf5d5cad objc_exception_throw + 48 2 CoreFoundation 0x00007fffaaf7ba0d +[NSException raise:format:] + 205 3 AppKit 0x00007fffa9323b44 _NSRunModal + 103 4 AppKit 0x00007fffa8dd757d -[NSAlert runModal] + 270 5 Clock Pro 0x000000010005aab8 _TFC9Clock_Pro14ViewController13AlarmAlertBoxfT_T_ + 344 6 Clock Pro 0x000000010002d053 _TFFC9Clock_Pro14ViewController5TimerFT_T_U_FT_T_ + 6563 7 Clock Pro 0x000000010000f317 _TTRXFo___XFdCb_ + 39 8 libdispatch.dylib 0x00000001009fe74d _d libc++abi.dylib: terminating with uncaught exception of type NSException
I use this code a lot in my project, and I haven't had problems those other lines of code. I've tried several things to fix this problem or work around it but I haven't been successful. Any help would be great.
Upvotes: 0
Views: 1181
Reputation: 47876
As already commented by Hamish, you need to run all UI related tasks on the main tread. It's not super difficult, someone who uses background thread should know:
Something like this:
if self.ReminderRingToneVar == "Spring" {
DispatchQueue.main.async {
let spring = NSSound(named: "Spring")
spring!.play()
self.AlarmAlertBox()
spring!.stop()
}
}
By the way, you'd better follow the standard coding rule of Swift, if you have any chance to share your code in a public space (I mean, including to write a question in a Q&A site): Use capital-CamelCase only for types.
Your code is hard to read.
Upvotes: 3