我有一个现有的OS X应用程序,在转换为Storyboards作为主界面后,我的app代理不再被使用。以前,MainMenu.xib有一个" App Delegate"对象,我可以将其类设置为我的app委托。但是,故事板不包含此类对象。
如何恢复AppDelegate并保留故事板?我觉得我错过了一些明显的东西。
答案 0 :(得分:6)
如果您没有将它指定为基于文档的应用程序,Xcode将创建一个AppDelegate.swift类并在应用程序场景中为您连接。
截至目前(Xcode Beta-2),新的基于文档的应用程序没有附带存根AppDelegate.swift文件。相反,有ViewController.swift和Document.swift。更糟糕的是,Document.swift文件错误地为文档实例化了相同的Main.storyboard。
这是我开始工作的一种方式:
创建AppDelegate类(例如:采用NSApplicationDelegate协议的NSObject)
将Object对象从Object库拖到Main.storyboard的Application Scene中,并将其设置为AppDelegate类。
按住Control键从应用程序场景中的Application对象拖动到AppDelegate对象,并连接其委托。
从Main.storyboard中删除其他所有内容,并为“文档”窗口创建一个新的Document.storyboard。更改Document.swift文件以实例化该Storyboard而不是Main。
如果您希望除文档窗口外还有一个主应用程序窗口和/或首选项窗口,请为这些窗口创建Application.storyboard和/或Preferences.storyboard,并使用AppDelegate类实例化他们。这样,AppDelegate可以自定义主窗口外观并执行其他方便的操作,包括接收从应用程序中的任何窗口发送的IBActions。
以下是基于文档的应用程序的AppDelegate.swift文件的工作示例,该应用程序还具有单独的主应用程序窗口和 非模态 偏好窗口:
// AppDelegate.swift
import Cocoa
class AppDelegate: NSObject, NSApplicationDelegate {
//init() {
// super.init()
// remove this if you don't use it
//}
var application: NSApplication? = nil
func applicationDidFinishLaunching(notification: NSNotification) {
application = notification.object as? NSApplication
let path = NSBundle.mainBundle().pathForResource("Defaults", ofType: "plist")
let defaults = NSDictionary(contentsOfFile:path)
NSUserDefaults.standardUserDefaults().registerDefaults(defaults)
NSUserDefaultsController.sharedUserDefaultsController().initialValues = defaults
NSUserDefaultsController.sharedUserDefaultsController().appliesImmediately = true
}
func applicationDidBecomeActive(notification: NSNotification) {
if application?.orderedDocuments?.count < 1 { showApplication(self) }
}
//func applicationWillFinishLaunching(notification: NSNotification) {
// remove this if you don't use it
//}
func applicationWillTerminate(notification: NSNotification) {
NSUserDefaults.standardUserDefaults().synchronize()
}
func applicationShouldOpenUntitledFile(app: NSApplication) -> Bool { return false }
func applicationShouldTerminateAfterLastWindowClosed(app: NSApplication) -> Bool { return false }
var applicationController: NSWindowController?
@IBAction func showApplication(sender : AnyObject) {
if !applicationController {
let storyboard = NSStoryboard(name: "Application", bundle: nil)
applicationController = storyboard.instantiateInitialController() as? NSWindowController
if let window = applicationController?.window {
window.titlebarAppearsTransparent = true
window.titleVisibility = NSWindowTitleVisibility.Hidden
window.styleMask |= NSFullSizeContentViewWindowMask
}
}
if applicationController { applicationController!.showWindow(sender) }
}
var preferencesController: NSWindowController?
@IBAction func showPreferences(sender : AnyObject) {
if !preferencesController {
let storyboard = NSStoryboard(name: "Preferences", bundle: nil)
preferencesController = storyboard.instantiateInitialController() as? NSWindowController
}
if preferencesController { preferencesController!.showWindow(sender) }
}
}
// AppDelegate.swift
import Cocoa
class AppDelegate: NSObject, NSApplicationDelegate {
//init() {
// super.init()
// remove this if you don't use it
//}
var application: NSApplication? = nil
func applicationDidFinishLaunching(notification: NSNotification) {
application = notification.object as? NSApplication
let path = NSBundle.mainBundle().pathForResource("Defaults", ofType: "plist")
let defaults = NSDictionary(contentsOfFile:path)
NSUserDefaults.standardUserDefaults().registerDefaults(defaults)
NSUserDefaultsController.sharedUserDefaultsController().initialValues = defaults
NSUserDefaultsController.sharedUserDefaultsController().appliesImmediately = true
}
func applicationDidBecomeActive(notification: NSNotification) {
if application?.orderedDocuments?.count < 1 { showApplication(self) }
}
//func applicationWillFinishLaunching(notification: NSNotification) {
// remove this if you don't use it
//}
func applicationWillTerminate(notification: NSNotification) {
NSUserDefaults.standardUserDefaults().synchronize()
}
func applicationShouldOpenUntitledFile(app: NSApplication) -> Bool { return false }
func applicationShouldTerminateAfterLastWindowClosed(app: NSApplication) -> Bool { return false }
var applicationController: NSWindowController?
@IBAction func showApplication(sender : AnyObject) {
if !applicationController {
let storyboard = NSStoryboard(name: "Application", bundle: nil)
applicationController = storyboard.instantiateInitialController() as? NSWindowController
if let window = applicationController?.window {
window.titlebarAppearsTransparent = true
window.titleVisibility = NSWindowTitleVisibility.Hidden
window.styleMask |= NSFullSizeContentViewWindowMask
}
}
if applicationController { applicationController!.showWindow(sender) }
}
var preferencesController: NSWindowController?
@IBAction func showPreferences(sender : AnyObject) {
if !preferencesController {
let storyboard = NSStoryboard(name: "Preferences", bundle: nil)
preferencesController = storyboard.instantiateInitialController() as? NSWindowController
}
if preferencesController { preferencesController!.showWindow(sender) }
}
}
答案 1 :(得分:0)
这是另一种便宜而简单的方法,如果你想要做的就是在它出现之前自定义主窗口的外观:
创建自己的NSWindowController子类,并将其连接为主窗口的 委托 。
将windowDidUpdate实现为窗口的挂钩,以便您可以设置所需的选项,还可以 删除 窗口委托,以便只调用一次该函数。这是完成这项工作所需的所有代码:
// WindowController.swift
import Cocoa
class WindowController: NSWindowController, NSWindowDelegate {
func windowDidUpdate(notification: NSNotification!) {
if let window = notification.object as? NSWindow! {
window.titlebarAppearsTransparent = true
window.titleVisibility = NSWindowTitleVisibility.Hidden
window.styleMask |= NSFullSizeContentViewWindowMask
window.delegate = nil }
}
}
实际上, 更简单 将这些外观选项应用于窗口的方法是使用Interface Builder将它们作为用户定义的运行时属性添加到NSWindow对象。您根本不需要子类化NSWindowController或编写任何代码。只需通过Identity Inspector窗格将这些值插入到窗口对象中:
Keypath: titlebarAppearsTransparent, Type: Boolean, Value: Checked
Keypath: titleVisibility, Type: Number, Value: 1
Keypath: styleMask, Type: Number, Value: 32783
当然,你不能指定styleMask的各个位,但它很容易将它们全部加在一起并得到一个数字来指定样式。
使用Storyboard架构,以及赋予NSViewController的新功能,不再需要继承NSWindowController的子类。