我有一个 Mac 应用程序,主要是用 AppKit 编写的。随着时间的推移,我在 SwiftUI 中添加新视图,并且一直使用 SwiftUI 预览来预览新的 SwiftUI 视图和旧的 AppKit 视图/视图控制器(请参阅预览不仅仅适用于 SwiftUI 视图)。
我遇到的一个麻烦是启动 SwiftUI 预览会打开我的应用程序的主窗口。这是预览如何通过常规启动流程的结果,例如调用applicationDidFinishLaunching(_:)
我的应用程序代理,这是我在启动时实例化并显示应用程序主窗口的地方。当然,如果我在预览中处理视图,我不希望发生这种情况。
我的 AppDelegate 如下所示:
@NSApplicationMain
public class AppDelegate: NSObject, NSApplicationDelegate {
lazy var mainWindowController = MainWindowController()
public func applicationDidFinishLaunching(_ aNotification: Notification) {
// Nasty hack :(
let isInSwiftUIPreview = ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1"
if !isRunningInTest() && !isInSwiftUIPreview {
mainWindowController.showWindow(self)
}
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
如您所见,如果此代码在测试或 SwiftUI 预览中运行,我添加了不显示主窗口的特殊情况。这味道让我觉得我做错了。
事实上,Apple 在Mastering Xcode Previews 的41:41 中提到了这个确切的问题。他们建议让您的应用程序具有场景感知能力,并使用 aUISceneDelegate
来完成这项工作。然而,这是一个仅限 iOS/catalyst 的 …
appkit nsapplication-delegate swift swiftui swiftui-previews
我有一个Mac OS X应用程序,它实现了 - (void)应用程序openFiles:方法来响应应用程序图标上的拖动文件.我在目标信息设置的文档类型部分中有一个允许的文件类型列表,Finder确实允许拖动,但是当pdf在拖动项目列表中时,我的委托方法被调用两次:一个用于所有元素而没有pdf,仅用于PDF.这当然使我无法正确处理这种情况.任何人都可以帮助我或解释发生了什么?谢谢
xcode cocoa objective-c nsapplication nsapplication-delegate
Cocoa应用程序有什么方法可以检测到用户何时尝试通过其Dock菜单而不是通过其他方法退出它?
通常,可以使用应用程序委托的applicationShouldTerminate:
方法捕获并响应退出事件。但是,此方法似乎无法区分来自应用程序主菜单,其Dock图标,来自Apple事件的退出请求,还是来自其他任何退出应用程序的常规方法。我很好奇是否有任何方法可以准确地知道用户如何尝试退出该应用程序。
我一直在尝试使用 Swift 3,但无法开始。以下代码正在编译,但它不会记录任何内容。好像applicationDidFinishLaunching
没有被调用。我在这里错过了一些关键部分吗?
来源/main.swift:
import AppKit
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(aNotification: NSNotification) {
NSLog("application start")
}
}
NSApplication.shared()
NSApp.setActivationPolicy(.regular)
let controller = AppDelegate()
NSApp.delegate = controller
NSApp.run()
Run Code Online (Sandbox Code Playgroud)
ps 有一个关于applicationDidFinishLaunching
被调用但不打印任何内容的类似问题。我相信事实并非如此,因为window.orderFrontRegardless()
代替日志记录对我也没有影响。
System Version: OS X 10.11.6
> swift --version
Apple Swift version 3.0 (swiftlang-800.0.43.6 clang-800.0.38)
Target: x86_64-apple-macosx10.9
Run Code Online (Sandbox Code Playgroud) 我想在应用程序终止时做一些事情,所以我向我的 AppDelegate 添加了applicationShouldTerminate:
和applicationWillTerminate
方法。但是,当我从 XCode 运行我的应用程序然后按 时\xe2\x8c\x98Q
,这两种方法都不会被调用。
现在我正在通过日志记录和调用进行测试printf
,当我退出应用程序时,我在任何地方都看不到任何输出。该文档似乎表明这应该有效。Google 尚未产生任何有用的结果,在 GitHub 上搜索示例代码大多会返回观察其他应用程序被终止的应用程序。
为什么没有applicationShouldTerminate:
被applicationWillTerminate
打电话?
这是我的应用程序委托中的这些方法实现:
\n\n- (NSApplicationTerminateReply)applicationShouldTerminate:(NSNotification *)aNotification {\n printf("printf applicationShouldTerminate");\n NSLog(@"NSLog applicationShouldTerminate");\n return NSTerminateNow;\n}\n\n- (void)applicationWillTerminate:(NSNotification *)aNotification {\n printf("printf applicationWillTerminate");\n NSLog(@"NSLog applicationWillTerminate");\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n(我还通过在 Xcode 中创建一个全新的项目进行了测试,您可以在https://github.com/noahlt/TestTerminator找到该项目)。
\nmacos cocoa objective-c nsapplication nsapplication-delegate
所以,这是我的情况:
我正在开发一个非标准的基于文档的应用程序,我想处理在任何文档中仍有未保存的更改时中止终止的情况.
我最初的想法是:
"Quit XXXXX"
菜单项或单击"X"
按钮)所以,我决定以委托方式来做.
在我的申请代表中,我实施了:
-windowToClose:
(触发NSWindowWillCloseNotification
)applicationShouldTerminate:
applicationShouldTerminateAfterLastWindowClosed:
现在,这就是我的想法.在applicationShouldTerminate:
方法中:
NSTerminateNow
如果不存在修改的文档则返回NSTerminateCancel
如果有修改过的文件则返回.在这种情况下,弹出一个警告表或类似的东西,如果用户确认他想要退出,然后拨打电话[NSApp terminate:nil];
这是正确的方法吗?
有什么建议?
cocoa objective-c terminate nsapplication nsapplication-delegate
停止按下确定在您看到retainCount
以下问题中的单词之前,请跳到底部的编辑,我已经说过我已经停止使用它.
我的Cocoa App使用MRRmain()
,在NSApplicationMain()
调用之前创建了许多全局资源,我正在加载它.由于NSApplicationMain()
没有返回,我已经使用atexit()
这样的方式来清理这些资源的清理:
atexit(cleanup);
if (![CocoaUtil initCocoaUtil] ||
![PreferenceController initPreferenceController] ||
![ResourceManager initResourceManager])
{
criticalAlertPanel(@"Failed to initialize application",
@"Failed to initialize application");
return 4;
}
retval = NSApplicationMain(argc, (const char **)argv);
Run Code Online (Sandbox Code Playgroud)
然而cleanup()
,在我的NSDocument
子类中dealloc
的任何视图都是'd(我缺少显示此消息的日志消息)之前调用它,因此有时候全局资源中的对象的引用计数> 1
.我过于谨慎并试图通过使用此方法释放我的全局资源来预先防止内存泄漏:
+ (void)fullRelease:(id)obj
format:(NSString *)format, ...
{
if (obj == nil)
return;
NSUInteger retainCount = [obj retainCount];
if (retainCount > 1)
{
va_list va;
va_start(va, format); …
Run Code Online (Sandbox Code Playgroud) 我注意到我的 NSApplication 委托回调中有一些奇怪的东西。当我启动带有调试器的应用程序时,我看到了我的期望:applicationDidFinishLaunching:
首先被调用,然后applicationDidBecomeActive:
当我在没有调试器的情况下运行应用程序时,我以相反的顺序收到调用:applicationDidBecomeActive:
在调用之前applicationDidFinishLaunching:
是否有一个原因?考虑基于调试器与非调试器的不同场景非常令人困惑。
[注意:测试这是在小牛队]
cocoa ×5
macos ×5
objective-c ×5
swift ×2
appkit ×1
exit ×1
nsdocument ×1
swiftui ×1
terminate ×1
xcode ×1