使用Xcode 6中的Storyboard的AppDelegate for Cocoa应用程序

时间:2014-06-12 20:18:20

标签: cocoa xcode6

我有一个现有的OS X应用程序,在转换为Storyboards作为主界面后,我的app代理不再被使用。以前,MainMenu.xib有一个" App Delegate"对象,我可以将其类设置为我的app委托。但是,故事板不包含此类对象。

如何恢复AppDelegate并保留故事板?我觉得我错过了一些明显的东西。

2 个答案:

答案 0 :(得分:6)

如果您没有将它指定为基于文档的应用程序,Xcode将创建一个AppDelegate.swift类并在应用程序场景中为您连接。

截至目前(Xcode Beta-2),新的基于文档的应用程序没有附带存根AppDelegate.swift文件。相反,有ViewController.swift和Document.swift。更糟糕的是,Document.swift文件错误地为文档实例化了相同的Main.storyboard。

这是我开始工作的一种方式:

  1. 创建AppDelegate类(例如:采用NSApplicationDelegate协议的NSObject)

  2. 将Object对象从Object库拖到Main.storyboard的Application Scene中,并将其设置为AppDelegate类。

  3. 按住Control键从应用程序场景中的Application对象拖动到AppDelegate对象,并连接其委托。

  4. 从Main.storyboard中删除其他所有内容,并为“文档”窗口创建一个新的Document.storyboard。更改Document.swift文件以实例化该Storyboard而不是Main。

  5. 如果您希望除文档窗口外还有一个主应用程序窗口和/或首选项窗口,请为这些窗口创建Application.storyboard和/或Preferences.storyboard,并使用AppDelegate类实例化他们。这样,AppDelegate可以自定义主窗口外观并执行其他方便的操作,包括接收从应用程序中的任何窗口发送的IBActions。

  6. 以下是基于文档的应用程序的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的子类。