Как использовать NSToolBar в Xcode 6 и раскадровке?

Я пытался создать приложение Cocoa, которое использует Swift и Storyboard в Xcode 6, но как я могу использовать NSToolbar там?

В Xcode 5 и xib вы можете добавить NSToolbar из библиотеки объектов в любые файлы .xib, а затем щелкнуть добавленную панель инструментов, чтобы развернуть ее, и перетащить соединение из любых элементов в файл AppDelegate.h. Таким образом вы можете создать соединение IBAction или IBOutlet. Я подтвердил, что это также можно сделать, если вы используете Swift и не раскадровку в Xcode 6. Однако похоже, что это не так в среде Xcode 6 и раскадровки.

Сначала я создал проект, который использует раскадровку в Xcode 6, но затем я не смог добавить NSToolbar из библиотеки объектов в контроллер представления в раскадровке. Поэтому я добавил его в объект Window Window Controller в раскадровке. Однако таким образом я не могу создать эти соединения из любых элементов на расширенной панели инструментов ни с AppDelegate.swift, ни с ViewController.swift.

Итак, мой вопрос:

  • Возможно ли создать приложение для раскадровки, использующее NSToolbar?
  • Если это возможно, является ли добавление NSToolbar к оконному контроллеру правильным способом использования NSToolBar в раскадровке?
  • Наконец, как я могу создать там соединения @IBOutlet и @IBAction?

ОБНОВИТЬ

Я обнаружил, что принятый ответ @GeorgeVillasboas работает только для @IBAction. Я все еще ищу, как создать соединение @IBOutlet...


person Blaszard    schedule 14.06.2014    source источник
comment
Посмотрите мой ответ...   -  person Grimxn    schedule 09.04.2015


Ответы (6)


У меня была такая же проблема. Решение работает как для проектов Objective-C, так и для проектов Swift.

Работая с раскадровками в OSX, он создает экземпляр NSWindow и переходит к другому NSViewController в качестве перехода содержимого окна, как вы описали.

В вашем ViewController создайте стандартный IBAction для получения действия при нажатии на панель инструментов. Чтобы связать его с NSToolbar, просто перетащите элемент управления (или перетащите его левой кнопкой мыши) из NSToolbarItem в объект FirstResponder, как показано на рисунке ниже.

Подключение NSToolbar на XCode 6

Откроется ОГРОМНЫЙ список доступных подключений. Ваш IBAction будет в этом списке. Просто выбрал его, и все готово.

Надеюсь это поможет!

person George Villasboas    schedule 17.07.2014
comment
Я установил соединение @IBAction между элементом панели инструментов и первым ответчиком, но метод все еще не выдается... - person Blaszard; 18.07.2014
comment
@Gardecolo, вам удалось поставить свой ViewController в качестве делегата вашего NSWindow? Здесь я собрал простой и рабочий пример этого в Swift. Вы должны быть в состоянии заставить его работать с ним. Надеюсь, поможет. Лучший. G. – github.com/ghvillasboas/SimpleNSToolbarWire - person George Villasboas; 18.07.2014
comment
Вы были правы, что проблема была в отсутствии принятия NSWindowDelegate и window.delegate = self. Это работало в пользовательском элементе панели инструментов, но не в элементе панели инструментов «Цвета» или «Шрифты», к вашему сведению. Но мне это не нужно, так что без проблем. Спасибо за вашу любезность. - person Blaszard; 18.07.2014
comment
@GeorgeVillasboas как насчет IBOutlets? Не нашел способ подключения. - person mohacs; 24.09.2014
comment
Apple нужно устроить барбекю и пригласить команды Cocoa и Cocoa Touch, чтобы они, наконец, могли встретиться и узнать друг друга и начать создавать единый набор элементов управления и API для OSX и iOS! И, кстати, Cocoa намного сложнее и проблематичнее, чем iOS. Пришло время команде Cocoa скопировать API-интерфейсы Cocoa Touch. Яблоко, я смотрю на тебя! - person Duck; 18.12.2014
comment
@GeorgeVillasboas Здравствуйте, сэр, я новичок в Swift с Java. Я выполнил все процедуры для NSToolbarItem для объекта FirstResponder, но я не понимаю, удалось ли вам поместить свой ViewController в качестве делегата вашего NSWindow? Можете ли вы объяснить это для меня. надеюсь поэтому у меня не работает - person Abin; 31.12.2014
comment
@Abin посмотрите этот пример проекта. Надеюсь, поможет. github.com/ghvillasboas/SimpleNSToolbarWire - person George Villasboas; 01.01.2015
comment
@GeorgeVillasboas Нет слов, чтобы выразить мою благодарность. Большое спасибо - person Abin; 02.01.2015
comment
Это сработало для меня. Также я смог подключиться к IBOutlet, сначала вручную создав код IBOutlet (например, @property (weak) IBOutlet NSSearchField *searchLocation;), а затем переведя XCode в режим редактора Assistant, показывающий элемент панели инструментов слева и код справа, затем rh мышь нажмите на элемент управления, чтобы вызвать его контекстное меню, а затем щелкните/перетащите из ссылки на выходы в код IBOutlet. - person gpdawson; 25.03.2015
comment
Работаю с раскадровками OS X уже месяц. Просто хотел добавить, что кажется, что NSWindowController, добавленный по умолчанию в раскадровку, является следующим в цепочке респондентов после его контроллера представления содержимого, и, таким образом, IBActions, добавленные в контроллер представления, также появляются в действиях первого респондента оконного контроллера. Мне тоже потребовалось немало времени, чтобы понять это. - person nstein; 05.06.2015

Вот ответ, который не полагается на подключения во время выполнения - ответ @cdalvaro получает большую часть пути для некоторых приложений, но не является полным, и требует, чтобы ViewController знал об искусственном NSWindowController, который не Я чувствую себя хорошо.

Как и @cdalvaro, первым шагом является создание собственного подкласса NSWindowController и установка WC Storyboard для этого класса. Затем вы можете создать все свои подключения к NSToolbar и обратно (оба @IBOutlets и @IBActions) в новом WindowController. Все идет нормально.

Последний шаг, который я больше нигде не видел, это как сослаться на ViewController в WindowController — вы не можете создать для него @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
    }
}
person Grimxn    schedule 09.04.2015

Это помогло мне найти решение IBOutlet, которое вы ищете: https://stackoverflow.com/a/27555237/3398062

Обновление (пояснение)

Я обнаружил этот поток, потому что пытался создать круговой индикатор выполнения внутри панели инструментов и не знал, как анимировать его из ViewController, поскольку IBOutlet был объявлен внутри пользовательского WindowController.

Наконец, я нашел сообщение, которое я добавил выше, в котором описывается, как получить доступ к IBOutlets из других классов.

По сути, я сделал следующее:

  • Создайте собственный подкласс NSWindowController (CustomWindowController) для оконного контроллера, чтобы я мог добавить IBOutlet для ProgressIndicator:

Пример кода:

@interface CustomWindowController : NSWindowController

@property (weak) IBOutlet NSProgressIndicator *progressIndicator;

@end
  • Затем в классе ViewController в методе, который я хочу использовать для обновления состояния индикатора прогресса, я создаю объект пользовательского оконного контроллера.

Пример кода:

CustomWindowController *customWindowController = self.view.window.windowController;`
  • Наконец, чтобы изменить состояние индикатора прогресса, достаточно вызвать метод из созданного пользовательского объекта.

Пример кода:

[customWindowController.progressIndicator startAnimation:sender];

or

[customWindowController.progressIndicator stopAnimation:sender];
person Carlos D. Álvaro    schedule 05.04.2015
comment
Хотя эта ссылка может быть решением проблемы, вы должны добавить больше деталей. - person abarisone; 05.04.2015

Это видео помогло мне создать панель инструментов, не написав ни строчки кода: https://www.youtube.com/watch?v=XSQocHG3IjA

Вы можете добавить элемент «Контроллер окна» из библиотеки объектов (если у вас его нет), подключиться к контроллеру представления (там, где вы хотите, чтобы отображалась панель инструментов) и следить за видео! Для пользовательских кнопок панели инструментов добавьте элемент «Кнопка изображения» на панель инструментов, просто перетащив его из библиотеки объектов. Затем вы можете выбрать изображение для кнопки, установить размер и так далее...

person balazs630    schedule 21.02.2017

Вот общее решение для розеток и действий. он позволяет вам выполнять все те же функции, что и 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, но, судя по ответам, которые я получил, это лучший вариант.

person nsij22    schedule 09.12.2014

Та же проблема с IBOutlets относится и к KVO. Одной из особенностей NSSplitViewController является свойство canCollapse для каждого элемента разделенного представления, который поддерживает KVO, но его нельзя использовать в IB, как и IBOutlets.

Единственный обходной путь, который я вижу, - это добавить NSObjectController к каждой сцене, а когда сцена загружается, установить объект контроллера объекта на объект в другой сцене (уже загруженный), на который вы хотите ссылаться.

person Mark Lilback    schedule 20.02.2015