Zoy*_*oyt 13 macos xcode swift
我正在尝试在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)
}
}
Run Code Online (Sandbox Code Playgroud)
无论是init或applicationDidFinishLaunching(_ aNotification: Notification)将被调用.任何帮助将非常感激.
War*_*ton 17
你需要在这里做一些事情
NSMainStoryboardFile从plist中删除键/值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")
}
}
Run Code Online (Sandbox Code Playgroud)
例如一个简单的代表.
@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)
}
}
Run Code Online (Sandbox Code Playgroud)
EDIT 2018已验证High Sierra
千万不要尝试做窗口或视图控制器初始化内init这将导致双重应用程序初始化问题和崩溃.该应用程序尚未在此阶段完成启动.等到applicationDidFinishLaunching任何重大操作开始.
Jam*_*rch 10
沃伦·伯顿(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
Run Code Online (Sandbox Code Playgroud)
我为此苦苦挣扎了好一阵子,但经过不小的实验,就提出了两个最新的解决方案。
@NSApplicationMain通过替代方法继续使用我发现您可以更改已接受答案的代码以解决该错误。为此,请不要super.init()在名为的类中调用方法AppDelegate。
真。我认为现在有一个过于急切的断言来计算由AppDelegate(或沿此行的一些逻辑)完成的初始化次数,因此对调用的super.init()计数以及该override init()块的完成也是如此。这里有两种解决方法:
不要叫super.init():这实际上是可能的,完全健康的NSObject,至少在MacOS上。但是,您将失去self在override init()块中引用的能力。
不要覆盖init()在所有:考虑像一个生命周期方法的过程中做你的init进程applicationWillFinishLaunching(:)。
我当然不推荐任何一个。
@NSApplicationMain完全放弃该方法@NSApplicationMain只是一个我们可以近似自己的宏。幸运的是,我遇到了James H Fisher的博客文章,解释了如何做。一会儿,我会引用重要的内容。
如果您写过@NSApplicationMain任何地方,请在继续执行这些说明之前将其删除。
Info.plist文件的key:value对应NSPrincipalClass保留其默认值:
<key>NSPrincipalClass</key>
<string>NSApplication</string>
Run Code Online (Sandbox Code Playgroud)
main.swift而不是子类化NSApplication该文件必须被调用main.swift; 这是Swift的“顶层不允许表达”规则的特殊例外。
import AppKit
let app = NSApplication.shared
let delegate = AppDelegate()
app.delegate = delegate
_ = NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv)
Run Code Online (Sandbox Code Playgroud)
James H Fisher解释并参考NSApplication 文档:
[文档]
每个应用都必须恰好具有的一个实例
NSApplication(或的子类NSApplication)。程序的main()函数应通过调用shared()class方法来创建此实例。[詹姆士]
首先,
main.swift运行NSApplication.shared,并将该NSApplication对象分配给myApp。请注意main(),即使在Swift中没有文档,文档也引用了函数!等效main.swift文件。接下来,
main.swift实例化你的AppDelegate类,并将其分配作为.delegate的myApp。现在,您可以看到为什么默认项目选择调用该类AppDelegate:将其设置为.delegateonNSApplication。最后,
main.swift调用该函数NSApplicationMain(...)。该函数NSApplicationMain(...)是Cocoa应用程序的入口点。NSApplicationMain(...)永不返回;而是设置UI事件循环,并最终使用Cexit(...)函数退出。
此外,此StackOverflow帖子还详细介绍了为什么要使用sharedApplication补救措施“创建多个应用程序”错误。
...这就是您所需要的!希望这有助于其他人。
如果有人正在寻找 Swift 版本(基于 @WarrenBurtons 的回答)。
应用程序代理
@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)
}
}
Run Code Online (Sandbox Code Playgroud)
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")
}
}
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
我还为此创建了一个要点,我将及时更新新的 Xcode / Swift 版本。 https://gist.github.com/florieger/7ac5e7155f6faf18666f92f7d82f6cbc
编辑:确保删除 Main.storyboard / MainMenu.xib,否则最终可能会在 UI 调试器中出现两个窗口。
| 归档时间: |
|
| 查看次数: |
2250 次 |
| 最近记录: |