You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从Dock退出时应用崩溃报Thread 1: signal SIGTERM错误

解决macOS应用从Dock右键退出时SIGTERM崩溃问题

问题描述

使用主文件+AppDelegate编写的macOS应用,从Dock右键选择“Quit”退出时,频繁在nsApplication.run()行崩溃,报错“Thread 1: signal SIGTERM”。已实现deinit、applicationShouldTerminate和applicationWillTerminate方法,但崩溃时控制台无日志输出;偶尔能正常退出并看到预期打印,ContentView为简单的“Hello, World!”视图。

代码片段

主文件

import Cocoa

let nsApplication: NSApplication = NSApplication.shared
let appDelegate: AppDelegate = AppDelegate()
nsApplication.delegate = appDelegate
nsApplication.run()

AppDelegate

import Cocoa
import SwiftUI

class AppDelegate: NSObject, NSApplicationDelegate {
    
    private lazy var window: NSWindow = NSWindow()
    
    deinit {
        print("AppDelegate is being deallocated")
    }
    
    func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply {
        print("terminateNow")
        return .terminateNow
    }
    
    func applicationWillTerminate(_ notification: Notification) {
        print("Application will terminate")
    }

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        window.styleMask = [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView]
        window.backingType = .buffered
        window.isReleasedWhenClosed = false
        window.center()
        window.setFrameAutosaveName("Main Window")
        window.title = "Window"
        window.isMovableByWindowBackground = true
        window.contentView = NSHostingView(rootView: ContentView())
        window.makeKeyAndOrderFront(nil)
    }
}

ContentView

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundColor(.accentColor)
            Text("Hello, world!")
        }
        .frame(width: 400.0, height: 200.0)
    }
}

解决方案

1. 完善应用初始化流程

手动启动NSApplication时,需明确设置应用激活策略,确保系统能正确识别应用状态,避免终止时的异常:
修改主文件代码:

import Cocoa

let nsApplication = NSApplication.shared
let appDelegate = AppDelegate()
nsApplication.delegate = appDelegate
nsApplication.setActivationPolicy(.regular) // 新增:设置应用为前台激活状态
nsApplication.run()

2. 主动清理终止时的资源

在applicationWillTerminate中手动关闭窗口,确保SwiftUI宿主视图及相关资源提前完成清理:

func applicationWillTerminate(_ notification: Notification) {
    print("Application will terminate")
    window.close() // 手动触发窗口资源释放
}

3. 调整窗口生命周期管理

将窗口的isReleasedWhenClosed改为true,让系统自动管理窗口的释放流程,减少手动控制的风险:

func applicationDidFinishLaunching(_ aNotification: Notification) {
    window.styleMask = [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView]
    window.backingType = .buffered
    window.isReleasedWhenClosed = true // 修改为自动释放窗口
    window.center()
    window.setFrameAutosaveName("Main Window")
    window.title = "Window"
    window.isMovableByWindowBackground = true
    window.contentView = NSHostingView(rootView: ContentView())
    window.makeKeyAndOrderFront(nil)
}

4. 改用标准启动方式(推荐)

如果无需手动控制NSApplication启动流程,使用系统标准的NSApplicationMain启动方式,由系统托管应用生命周期,避免手动初始化的边缘问题:
替换主文件代码:

import Cocoa

NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv)

并在Info.plist中添加配置:

  • 设置NSPrincipalClass为NSApplication
  • 设置NSMainNibFile为空字符串
  • 添加NSApplicationDelegateClass,值为你的AppDelegate类的完整类名(例如$(PRODUCT_MODULE_NAME).AppDelegate)

或直接在AppDelegate类上添加@NSApplicationMain注解,自动完成上述配置:

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
    // ... 原有代码 ...
}

原因说明

崩溃的核心是手动初始化NSApplication时,应用状态未正确设置,或终止流程中资源清理不及时,导致系统发送SIGTERM信号时出现内存访问异常。上述方案通过规范应用状态、主动清理资源或交由系统托管生命周期,解决了竞态条件和资源残留问题。

内容的提问来源于stack exchange,提问作者Mango

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 11:35:11