如何在Xcode 6和Storyboard中使用NSToolBar?

时间:2014-06-14 11:28:00

标签: xcode cocoa swift storyboard nstoolbar

我一直在尝试在Xcode 6中使用Swift和Storyboard的Cocoa应用程序,但是如何在那里使用NSToolbar

在Xcode 5和xib中,您可以从对象库中将NSToolbar添加到任何.xib文件,然后单击添加的工具栏以展开它,并将连接从那里的任何项拖放到{{ 1}}文件。通过这种方式,您可以创建AppDelegate.hIBAction连接。我确认如果你在Xcode 6中使用Swift和非故事板,也可以这样做。但是,在Xcode 6和Storyboard环境中看起来并非如此。

我首先创建了一个在Xcode 6中使用Storyboard的项目,但是后来,我无法在对象库中将IBOutlet添加到Storyboard中的View Controller。所以我将它添加到Storyboard中的Window Controller的Window对象中。但是,通过这种方式,我无法将展开工具栏中任何项目的这些连接创建为NSToolbarAppDelegate.swift

所以我的问题是:

  • 创建使用ViewController.swift
  • 的情节提要应用是否可行
  • 如果可行,是否在窗口控制器中添加了NSToolbar在Storyboard中使用NSToolbar的正确方法?
  • 最后,如何在那里创建NSToolBar@IBOutlet个连接?

更新

我发现@GeorgeVillasboas接受的答案仅适用于@IBAction。我仍在寻找如何创建@IBAction连接...

6 个答案:

答案 0 :(得分:24)

我遇到了同样的问题。 该解决方案适用于Objective-C和Swift项目。

在OSX上使用Storyboard,它会创建一个NSWindow实例,并按照你的描述将其作为其Window Content Segue转移到另一个NSViewController。

在ViewController上,创建标准IBAction以在单击工具栏时接收操作。要使用NSToolbar连接它,只需从NSToolbarItem控制拖动(或左键拖动)到FirstResponder对象,如下图所示。

Wiring up a NSToolbar on XCode 6

这将打开一个 HUGE 可用连接列表。您的IBAction将在该列表中。 只是选择了它,你就可以了。

希望这有帮助!

答案 1 :(得分:10)

这里有一个不依赖于运行时连接的答案 - @ cdalvaro的答案大部分都适用于某些应用程序,但并不完整,它需要ViewController知道人为的NSWindowController,这感觉不对。

与@cdalvaro一样,第一步是构建自己的NSWindowController子类,并将Storyboard WC设置为该类。然后,您可以在新的WindowController中创建与NSToolbar@IBOutlet s& @IBAction)之间的所有连接。到目前为止一切都很好。

我还没有在其他任何地方看到的最后一步是如何在WindowController中引用ViewController - 你不能为它创建一个@IBOutlet,原因与之相同。我们首先来到这里 - 你不能在故事板中的场景中创建引用。但是,WindowController必须具有对ViewController的引用,并且它具有... self.window!.contentViewController! as! ViewController

这是一个完整的WindowController,带有一个复选框,用于设置ViewController中的值,,而ViewController不需要知道任何内容 ...

class MyWindowController: NSWindowController {

    var viewController: ViewController {
        get {
            return self.window!.contentViewController! as! ViewController
        }
    }

    @IBOutlet weak var aSwitch: NSButton!
    @IBAction func toolbarActionA(sender: AnyObject) {
        println("toolbarActionA")
        self.viewController.a = !self.viewController.a
        self.aSwitch.state = self.viewController.a ? NSOnState : NSOffState
    }
}

答案 2 :(得分:3)

这有助于我找到您正在寻找的IBOutlet解决方案: https://stackoverflow.com/a/27555237/3398062

更新(说明)

我发现了这个帖子,因为我试图在工具栏中创建一个循环进度指示器,我不知道如何在ViewController中设置动画,因为IBOutlet是在自定义的WindowController中声明的。

最后,我发现上面添加的帖子描述了如何从其他类访问IBOutlets。

实质上我所做的是以下内容:

  • 为Window Controller创建一个自定义的NSWindowController子类(CustomWindowController),这样我就可以为ProgressIndicator添加IBOutlet:

代码示例:

@interface CustomWindowController : NSWindowController

@property (weak) IBOutlet NSProgressIndicator *progressIndicator;

@end
  • 然后在ViewController类中,在我想用来更新进度指示器状态的方法中,我创建了自定义Window Controller的对象。

代码示例:

CustomWindowController *customWindowController = self.view.window.windowController;`
  • 最后,要更改进度指示器的状态,只需从创建的自定义对象中调用该方法。

代码示例:

[customWindowController.progressIndicator startAnimation:sender];

[customWindowController.progressIndicator stopAnimation:sender];

答案 3 :(得分:2)

此视频帮助我创建了一个工具栏而无需编写任何代码:https://www.youtube.com/watch?v=XSQocHG3IjA

您可以添加'窗口控制器'对象库中的项目(如果您没有),连接到视图控制器(您希望工具栏显示的位置)并关注视频!对于自定义工具栏按钮,添加'图像按钮'通过从对象库拖动项目到工具栏。然后你可以选择按钮的图像,设置大小等等......

答案 4 :(得分:0)

这是出口和行动的一般解决方案。它允许您为工具栏项预先形成所有与iboutlet相同的功能,并允许您将按钮设置为函数而不是创建ibaction。希望它有所帮助:P

override func viewDidLayout() {
var x = self.view.window?.toolbar?.items[1].label
println(x)
if(self.view.window?.toolbar?.items[0].label! != "Check")
{
    toobarediting()
}
println("didlay")
}

func toobarediting() {
self.view.window?.toolbar?.insertItemWithItemIdentifier("Check", atIndex: 0)
}

func toolbarcheck(functiontoset: Selector) {
var y = self.view.window?.toolbar?.items[0] as NSToolbarItem
y.action = functiontoset
if(functiontoset != nil)
{
    y.enabled = true
}
}

这是我试图获得更清晰答案的问题的链接 http://www.stackoverflow.com/questions/27371439/use-nstoolbar-outlet-xcode-6-and-storyboard/27374449 但从目前为止我得到的答案看起来这是最好的选择。

答案 5 :(得分:0)

IBOutlets的同样问题也适用于KVO。 NSSplitViewController的一个功能是支持KVO的每个拆分视图项的canCollapse属性,但这在IB中就像IBOutlets一样无法使用。

我能看到的唯一解决方法是向每个场景添加一个NSObjectController,当场景加载时,将对象控制器的对象设置为您想要引用的另一个场景(已加载)中的对象。