Nathanael Carper
Nathanael Carper

Reputation: 312

Weird error when executing code in Xcode 8

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:

I'm getting this weird error.

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

Answers (1)

OOPer
OOPer

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

Related Questions