【问题标题】:OSX application without storyboard or xib files using Swift没有使用 Swift 的故事板或 xib 文件的 OSX 应用程序
【发布时间】:2015-03-01 10:54:21
【问题描述】:

不幸的是,我在 Internet 上没有找到任何有用的东西 - 我想知道,在不使用 Swift 中的情节提要或 XIB 文件的情况下,我实际上必须键入哪些代码来初始化应用程序。我知道我必须有一个名为main.swift 文件。但我不知道在那里写什么(比如我需要自动释放池或类似的东西吗?)。例如,我将如何初始化NSMenu 以及如何将NSViewController 添加到活动窗口(iOS 的类似.rootViewController 没有帮助)。感谢您的帮助;)

编辑: 我实际上不想在AppDelegate 前面使用@NSApplicationMain。我宁愿知道那里到底发生了什么,然后自己做。

【问题讨论】:

  • 我不知道你为什么要回避@NSApplicationMain,但这个问题在幕后确实具有很好的教育价值!

标签: macos cocoa swift


【解决方案1】:

如果您不想拥有 @NSApplicationMain 属性,请执行以下操作:

  1. 有一个文件 main.swift

  2. 添加以下顶级代码:

     import Cocoa
    
     let delegate = AppDelegate() //alloc main app's delegate class
     NSApplication.shared.delegate = delegate //set as app's delegate
     NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv) //start of run loop       
    
     // Old versions:
     //  NSApplicationMain(C_ARGC, C_ARGV)
     //  NSApplicationMain(Process.argc, Process.unsafeArgv);  
    

其余的应该在您的应用委托中。例如:

import Cocoa

class AppDelegate: NSObject, NSApplicationDelegate {
    var newWindow: NSWindow?
    var controller: ViewController?
    
    func applicationDidFinishLaunching(aNotification: NSNotification) {
        newWindow = NSWindow(contentRect: NSMakeRect(10, 10, 300, 300), styleMask: .resizable, backing: .buffered, defer: false)
        
        controller = ViewController()
        let content = newWindow!.contentView! as NSView
        let view = controller!.view
        content.addSubview(view)
        
        newWindow!.makeKeyAndOrderFront(nil)
    }
}

那么你有一个 viewController

import Cocoa

class ViewController : NSViewController {
    override func loadView() {
        let view = NSView(frame: NSMakeRect(0,0,100,100))
        view.wantsLayer = true
        view.layer?.borderWidth = 2
        view.layer?.borderColor = NSColor.red.cgColor
        self.view = view
    }
}

【讨论】:

  • 我如何在窗口上显示几个视图控制器?或者我应该在需要时使用不同的窗口隐藏和显示?或者是否还有其他努力可以做到这一点?
  • 我同意 leonardo 的观点,对于更复杂的东西你应该使用 xibs——我不经常使用,但如果你被困在这个水平上,我会这样做
  • 抱歉,这不是“为我编写所有代码” - 您的问题得到了 100% 的回答,您可以提出不同的具体问题,或者(最好)尝试一些教程
  • 在 Swift 3.1 中是 func applicationDidFinishLaunching(_ notification: Notification)。纯粹的复制和粘贴让我有些困惑。
  • 当我用 Xcode 9 尝试这个时,应用程序终止并抱怨它找不到 xib 文件。我在哪里告诉 NSApplication 不要使用 xib 文件?
【解决方案2】:

上面的顶级代码示例不再适用于最新版本的 Xcode。而是使用这个:

import Cocoa

let delegate = AppDelegate() //alloc main app's delegate class
NSApplication.shared().delegate = delegate //set as app's delegate

let ret = NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv)

【讨论】:

  • 在 Swift 4 中不再工作。我花了几个小时,仍然没有运气以编程方式创建一个纯 swift 的窗口。 Apple 做起来太难了(\阅读没有故事板的官方入门指南)
  • @Kun 你找到解决方案了吗?
  • @BohdanSavych 我做了,shared 现在是一个计算属性,所以在那之后去掉括号。
【解决方案3】:

在 Swift 4 中,它又略有变化,

主文件必须有

import Cocoa

let delegate = AppDelegate()
NSApplication.shared.delegate = delegate

NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv)

AppDelegate 必须是

import Cocoa


class AppDelegate: NSObject, NSApplicationDelegate {
    var newWindow: NSWindow?
    var controller: ViewController?

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        newWindow = NSWindow(contentRect: NSMakeRect(10, 10, 300, 300), styleMask: .resizable, backing: .buffered, defer: false)

        controller = ViewController()
        let content = newWindow!.contentView! as NSView
        let view = controller!.view
        content.addSubview(view)

        newWindow!.makeKeyAndOrderFront(nil)
    }
}

视图控制器是一样的

【讨论】:

  • 对于像我这样希望制作显示标题框的窗口的人window = NSWindow(contentRect: winSize, styleMask: [.miniaturizable, .closable, .resizable, .titled], backing: .buffered, defer: false)
【解决方案4】:

我使用的是 Swift 5,虽然我的应用程序可以使用来自 Noskcaj 答案的代码,但我从现有的 nib 文件中看到了一堆 [Nib Loading] Failed to connect... 错误。我通过在我的 main.swift 中使用它来修复它:

import Cocoa

autoreleasepool {
 let delegate = AppDelegate()
 // NSApplication delegate is a weak reference,
 // so we have to make sure it's not deallocated.
 withExtendedLifetime(delegate, {
     let application = NSApplication.shared
     application.delegate = delegate
     application.run()
     application.delegate = nil
 })
}

参考:https://stackoverflow.com/a/54239088

【讨论】:

    猜你喜欢
    • 2012-07-04
    • 2016-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-31
    • 1970-01-01
    相关资源
    最近更新 更多