Home > Back-end >  EXC_BAD_ACCESS Issue with closing a Window in macOS Cocoa
EXC_BAD_ACCESS Issue with closing a Window in macOS Cocoa

Time:02-04

This codes works well until I want close about window with mouse or using keyboard with command w, when I close my about window an Error happen:

Error:

Thread 1: EXC_BAD_ACCESS (code=1, address=0x20)

Not sure why this error happen and how to solve the issue! By the way I am using a main file for loading my app like this:

import Cocoa

// **** Main **** //
let nsApplication = NSApplication.shared
let appDelegate = AppDelegate()
nsApplication.delegate = appDelegate
nsApplication.run()

And this is my all codes:

import Cocoa
import SwiftUI

class AppDelegate: NSObject, NSApplicationDelegate {
    
    private var window: NSWindow!
    
    func applicationDidFinishLaunching(_ aNotification: Notification) {
        
        buildMainMenu()
        
        buildWindow()
        
    }
    
    func buildWindow() {
        window = NSWindow(
            contentRect: NSRect(x: 0, y: 0, width: 100.0, height: 100.0),
            styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
            backing: .buffered, defer: false)
        
        window.center()
        window.setFrameAutosaveName("Main Window")
        window.title = "No Storyboard Window"
        window.makeKeyAndOrderFront(window)
    }
    
    func buildMainMenu() {
        
        let appMainMenu: NSMenu = NSMenu()
        
        let mainMenu: NSMenuItem = NSMenuItem()
        mainMenu.submenu = NSMenu(title: "MainMenu")
        
        let mainMenuItem0 = NSMenuItem(title: "About", action: #selector(NSApplication.about), keyEquivalent: "a")
        mainMenuItem0.keyEquivalentModifierMask = .command
        
        let mainMenuItem1 = NSMenuItem(title: "Close", action: #selector(NSWindow.performClose(_:)), keyEquivalent: "w")
        mainMenuItem1.keyEquivalentModifierMask = .command
        
        let mainMenuItem2 = NSMenuItem(title: "Quit", action: #selector(NSApplication.shared.terminate(_:)), keyEquivalent: "q")
        mainMenuItem2.keyEquivalentModifierMask = .command
        
        mainMenu.submenu?.items = [mainMenuItem0, mainMenuItem1, mainMenuItem2]
        appMainMenu.items = [mainMenu]
        
        NSApp.mainMenu = appMainMenu
        
    }
    
}


extension NSApplication {
    @objc func about() {
        AboutView().openInWindow(title: "About My App", sender: self)
    }
}

struct AboutView: View {
    var body: some View {
        Color.green
            .frame(width: 500, height: 200)
    }
}

extension View {
    @discardableResult
    func openInWindow(title: String, sender: Any?) -> NSWindow {
        
        let window = NSWindow(
            contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
            styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
            backing: .buffered, defer: false)
        
        window.center()
        window.contentView = NSHostingView(rootView: self)
        window.title = title
        window.makeKeyAndOrderFront(sender)
        return window
    }
}

CodePudding user response:

One line of code fixes it: window.isReleasedWhenClosed = false added to the function openInWindow(). Reference is here:https://developer.apple.com/forums/thread/651592 . Your original code would destroy the about window object each time it was opened and closed. By not allowing it to do that your code runs without error. Make this substitution.

extension View {
    @discardableResult
    func openInWindow(title: String, sender: Any?) -> NSWindow {
        
        let window = NSWindow(
            contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
            styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
            backing: .buffered, defer: false)
        
        window.center()
        window.isReleasedWhenClosed = false
        window.contentView = NSHostingView(rootView: self)
        window.title = title
        window.makeKeyAndOrderFront(sender)
        return window
    }
}

  • Related