我正在尝试在macOS Sierra上的Xcode 8(稳定版)中创建一个没有故事板的macOS应用程序。但是,我的AppDelegate
甚至没有被启动。这是我的代码:
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
var window: NSWindow!
override init() {
super.init()
print("Init")
}
func applicationDidFinishLaunching(_ aNotification: Notification) {
print("Finished launching")
// Create a window
window = NSWindow()
// Add the view controller
let viewController = ViewController()
window.contentView?.addSubview(viewController.view)
// Show the window
window.makeKeyAndOrderFront(nil)
}
}
正在调用init
或applicationDidFinishLaunching(_ aNotification: Notification)
。任何帮助将不胜感激。
答案 0 :(得分:15)
你需要在这里做一些事情
NSMainStoryboardFile
键/值
NSApplication
子类并将其分配给Principal Class (NSPrincipalClass)
键。 名称必须完全符合您的模块名称。
delegate
属性。 确保对代理对象保持强引用。我刚刚在这里使用let
。
class GrookApplication: NSApplication {
let strongDelegate = AppDelegate()
override init() {
super.init()
self.delegate = strongDelegate
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
例如一个简单的代表。
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
override init() {
super.init()
print("wassup")
//conceptual proof of life init override
//wait until applicationDidFinishLaunching , specially for UI
}
var window: NSWindow!
func applicationDidFinishLaunching(_ aNotification: Notification) {
print("yo! I'm alive")
window = NSWindow(contentRect: NSRect(x: 0, y: 0, width: 200, height: 200), styleMask: .titled, backing: .buffered, defer: false)
window.makeKeyAndOrderFront(nil)
}
}
EDIT 2018 已验证High Sierra
不尝试在init
内执行窗口或查看控制器初始化,这会导致双应用初始化问题和崩溃。该应用程序尚未在此阶段完成启动。等到applicationDidFinishLaunching
开始任何重要操作。
答案 1 :(得分:6)
Warren Burton接受了答案,利用对@NSApplicationMain
- 带注释的AppDelegate实例的强引用不再有效。我已经在OS X High Sierra上证实了这一点,Alex Sieroshtan评论说它在OS X Yosemite中也没有回复。正如Tyler Durden所指出的那样,失败点就是这样的信息:
Assertion failure in -[X.XApplication init], /Library/Caches/com.apple.xbs/Sources/AppKit/AppKit-1504.82.104/AppKit.subproj/NSApplication.m:1778
2017-04-08 13:25:35.761585+0100 X
[9073:1059806][General] An uncaught exception was raised 2017-04-08 13:25:35.761601+0100 X
[9073:1059806][General] Creating more than one Application
我自己一直在努力解决这个问题,但是通过不小的实验来提出两个最新的解决方案。
@NSApplicationMain
我发现您可以更改已接受答案的代码以解决该问题。这样做的方法是不要在名为super.init()
的类中调用AppDelegate
方法。
真。我认为有一个过于急切的断言来计算AppDelegate
(或沿着这些行的某些逻辑)完成的次数,因此对super.init()
的调用以及{override init()
的完成都会被计算。 1}}阻止。这里有两种解决方法可供选择:
请勿拨打super.init()
:这实际上是可行的completely healthy NSObject
,至少在macOS中。但是,您无法在self
区块中引用override init()
。
根本不要覆盖init()
:考虑在applicationWillFinishLaunching(:)
等生命周期方法中执行初始化过程。
当然,我不推荐其中任何一种。
@NSApplicationMain
方法 @NSApplicationMain
只是一个我们可以近似的宏。幸运的是,我遇到了James H Fisher的blog post解释如何。我将在短时间内引用重要内容。
如果您已将@NSApplicationMain
写入任何地方,请在继续执行这些说明之前将其删除。
Info.plist
文件 NSPrincipalClass
的键:值对应保持其默认值:
<key>NSPrincipalClass</key>
<string>NSApplication</string>
main.swift
而不是子类化NSApplication
该文件必须被称为main.swift
;它是special exception到斯威夫特&#34;表达式不允许在顶级&#34;规则。
import AppKit
let app = NSApplication.shared
let delegate = AppDelegate()
app.delegate = delegate
_ = NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv)
James H Fisher解释说,参考NSApplication
documentation:
<强> [文件] 强>
每个应用必须只有一个
NSApplication
实例(或NSApplication
的子类)。您的程序的main()
函数应该通过调用shared()
类方法来创建此实例。<强> [詹姆斯] 强>
首先,
main.swift
运行NSApplication.shared
,并将此NSApplication
对象分配给myApp
。请注意,文档引用了main()
函数,即使在Swift中也没有!等效的是main.swift
文件。接下来,
main.swift
实例化您的AppDelegate
课程,并将其指定为.delegate
myApp
。您现在可以看到默认项目选择调用类AppDelegate
的原因:它被设置为.delegate
上的NSApplication
。最后,
main.swift
调用函数NSApplicationMain(...)
...函数NSApplicationMain(...)
是Cocoa应用程序的入口点。NSApplicationMain(...)
永远不会回来;相反,它设置了UI事件循环,最终使用Cexit(...)
函数退出。
另外this StackOverflow post详细介绍了为什么使用sharedApplication
补救&#34;创建多个应用程序&#34;错误。
......这就是你所需要的!希望这有助于帮助其他人。
答案 2 :(得分:1)
如果有人正在寻找Swift版本(基于@WarrenBurtons答案)。
<强>的AppDelegate 强>
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
var window: NSWindow?
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
window = NSWindow(contentViewController: RootViewController())
window?.makeKeyAndOrderFront(self)
}
}
class RootViewController: NSViewController {
override func loadView() {
self.view = NSView()
self.view.frame = NSRect(x: 0, y: 0, width: 600, height: 400)
}
}
NSApplication子类
import Cocoa
class Application: NSApplication {
let strongDelegate = AppDelegate()
override init() {
super.init()
self.delegate = strongDelegate
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
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>NSPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).Application</string>
...
</dict>
</plist>
我也为此创建了一个要点,我将及时了解新的Xcode / Swift版本。 https://gist.github.com/florieger/7ac5e7155f6faf18666f92f7d82f6cbc
编辑确保删除Main.storyboard / MainMenu.xib,否则您最终可能会在UI调试器中使用两个Windows。