如果我不使用storyboard/XIB文件,设置原理类不会影响NSApplication.shared实例化的类

问题描述 投票:0回答:1

背景:

我想使用

NSApplication
的自定义子类来创建应用程序实例。这是
NSApplication.shared
返回的对象的类。我尝试过以下方法:

class Application: NSApplication {
    // My own items
}

然后我尝试将主要类别

NSApplication
设置为
Application
以及
$(PRODUCT_MODULE_NAME).Application
中的
Info.plist
。然后,我尝试通过尝试 
print(NSApplication.shared as! Application)
来确认此操作是否有效,但这会中止程序,这意味着应用程序实例的类尚未成功设置为我的自定义类。我怎样才能做到这一点?

我知道我能做到:

extension NSApplication {
    // My own items
}

但是有什么方法可以用子类而不是扩展来做到这一点,从而使我的子类实际上被实例化?

最小可重现示例:

模块名称添加到主类字符串似乎只能在具有 .storyboard/

.xib
文件的
'正常'
应用程序中工作。
如果我创建一个新的 macOS 应用程序模板,并执行 only答案中指定的修改,没有问题。

但是,通过删除

.storyboard
/
.xib
并将
AppDelegate.swift
替换为
main.swift
,我能够在新项目中重现此问题,如下所示:

import Cocoa
class Application: NSApplication, NSApplicationDelegate {
    func applicationShouldTerminateAfterLastWindowClosed(_ _: NSApplication) -> Bool {
        return true
    }
}
NSApplication.shared.delegate = (NSApp as! Application)
NSApp.run()

我还使

Info.plist
包含以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleDevelopmentRegion</key>
    <string>$(DEVELOPMENT_LANGUAGE)</string>
    <key>CFBundleExecutable</key>
    <string>$(EXECUTABLE_NAME)</string>
    <key>CFBundleIconFile</key>
    <string></string>
    <key>CFBundleIdentifier</key>
    <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>CFBundleName</key>
    <string>$(PRODUCT_NAME)</string>
    <key>CFBundlePackageType</key>
    <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
    <key>CFBundleShortVersionString</key>
    <string>1.0</string>
    <key>CFBundleVersion</key>
    <string>1</string>
    <key>LSMinimumSystemVersion</key>
    <string>$(MACOSX_DEPLOYMENT_TARGET)</string>
    <key>NSPrincipalClass</key>
    <string>$(PRODUCT_MODULE_NAME).Application</string>
    <key>NSSupportsAutomaticTermination</key>
    <true/>
    <key>NSSupportsSuddenTermination</key>
    <true/>
</dict>
</plist>

仅此而已。项目中唯一的文件是如上所示的

main.swift
Info.plist
以及未修改的
Assets.xcassets
.entitlements
文件。同样,我在 Xcode 中使用新的 macOS 应用程序模板完成了此操作。

问题的另一个证明是这个断言失败了:

assert(type(of: NSApplication.shared) == Bundle.main.principalClass!)

Bundle.main.principalClass
的值是预期的,但
NSApplication.shared
由于某种原因没有实例化这种类型的类。

swift macos cocoa appkit nsapplication
1个回答
3
投票

您需要确保

Principal class
包含正确的模块名称才能加载。

这很好用:

@main
class AppDelegate: NSObject, NSApplicationDelegate {
    func applicationDidFinishLaunching(_ aNotification: Notification) {
        print("NSApp:", NSApplication.shared as! MyApplication)
    }
}

class MyApplication: NSApplication {
    
}

哪个打印:

NS应用程序:

© www.soinside.com 2019 - 2024. All rights reserved.