I’m writing an app that burns to optical disks and there’s a strange problem when returning from the burn progress panel. Any attempt to read one of the AppDelegate ivars after a disc burn causes a crash. The chain of events is:
User presses burn button > DRSetupPanel is presented > user presses OK > DRBurnProgressPanel is displayed and a track is burnt to disc > AppDelegate receives a notification of burn finishing.
It's at this point, during the handling of receiving a finshed notification, that I suddenly can't access an array that is held by the AppDelegate. I can read it's count but any attempt to directly access an element causes a crash as though it had been deallocated. I can access elements just fine before the progress panel is presented.
I call the disk recording setup sheet like this:
let setup_panel = DRBurnSetupPanel()
let passed = UnsafeMutableRawPointer(Unmanaged.passUnretained(self.disk_buckets[current_burn_disk]).toOpaque())
setup_panel.beginSetupSheet(for: self.window, modalDelegate: self, didEnd: #selector(self.burnSetupPanelDidEnd(_:return_code:context_info:)), contextInfo: passed)
disk_buckets is an array of classes each containing a reference to a DRTrack to be burnt - I pass an element so that I can deal with the DRTrack reference later.
After the setup panel is dismissed, the following method is then called:
func burnSetupPanelDidEnd(_ panel: DRBurnSetupPanel, return_code: Int, context_info: UnsafeMutableRawPointer) {
//…. some code ….
var track:DRTrack = self.disk_buckets[self.current_burn_disk].vDRTrack!
NotificationCenter.default.addObserver(self, selector: #selector(self.progressDidEnd), name: NSNotification.Name(rawValue: BTVDiscBurnDidEndNotification), object: nil)
self.objc_panel.presentDiscProgressPanel(self.window, burner: panel.burnObject(), layout: track!)
}
objc_panel is a obj-c singleton that initialises and presents a disc burning progress panel (I did it this way as doing it directly from Swift is buggy - the progress panel is displayed as a tiny window instead of the default OS one - bug report has been sent to Apple). When the burn finishes the objc_panel posts a "BTVDiscBurnDidEndNotification" notification to let the AppDelegate know it’s finished which in turn calls:
func progressDidEnd(_ note: Notification?) {
print (“DEBUG count: \(self.disk_buckets.count)")
print (“DEBUG first element: \(self.disk_buckets[0])")
//…. more code ….
}
All goes well until the end of ths chain when any attempt to access the first element (or any, for that matter), i.e. the print statement on line 03 causes a crash:
2016-10-04 14:01:34.654 DiskSpan[4025:220213] *** -[DiskSpan.BackupDisk retain]: message sent to deallocated instance 0x6000cafc0f40
(BackupDisk being the class that populates the array)
The thing is that the first print line outputs a correct count of the array i.e. 1.
So how come I can't access anything in the array during a notification post? It should be noted that this worked under Swift 2 and has only become a problem since Swift 3!