Как инициировать действие из NSTableCellView в представлении на основе NSTableView при использовании привязок

Я столкнулся с проблемой NSTableView на основе представления, работающего на 10.8 (цель 10.7, но я думаю, что это не имеет значения).

Я использую NSTableView и получаю значения содержимого для своего пользовательского NSTableCellView через привязки. Я использую obejctValue NSTableCellView для получения своих данных.

Я добавил кнопку в свою ячейку и хотел бы, чтобы она вызывала какое-то действие при нажатии. До сих пор мне удалось вызвать действие только в пользовательском подклассе NSTableCellView.

Я могу получить строку, по которой щелкнули, используя цепочку:

NSButton *myButton = (NSButton*)sender;    

NSTableView *myView = (NSTableView*)myButton.superview.superview.superview;

NSInteger rowClicked = [myView rowForView:myButton.superview];

Оттуда я не знаю, как добраться до моего делегата приложения или контроллера, где определено действие.

Поскольку я использую привязки какао, у меня нет делегата в NSTableView, который я мог бы использовать для запуска своего действия.

Ты хоть представляешь, как я мог возразить диспетчеру?

Спасибо заранее!


person Olivier Pallière    schedule 04.09.2012    source источник


Ответы (4)


Хотя вы используете привязки, вы все равно можете установить свой контроллер в качестве делегата для вашего табличного представления в построителе интерфейса.

Я вижу, что вы уже можете получить доступ к табличному представлению из своей ячейки. Следующая задача должна быть простой: просто установите делегат табличного представления в качестве цели для действия вашей кнопки.

person Suhas    schedule 05.09.2012
comment
Спасибо, нашел как вы сказали. На самом деле сначала был сбит с толку тем, что мне нужно было поставить ячейку. Но это работает нормально. - person Olivier Pallière; 06.09.2012

Спасибо за ваш вопрос, я также буду запускать действие с помощью кнопки в NSTableView. Ваш вопрос помог мне направить меня на правильный путь.

Сначала обратимся к вашему решению, чтобы найти номер строки, на котором находится мой NSTableView. Я смог найти его, не зная кнопки, в своем пользовательском NSTableView я установил следующее в качестве первой попытки:

- (NSInteger)myRowNumber  
{  
    return [(NSTableView*)self.superview.superview rowForView:self];  
}

это работает нормально, однако это менее надежно. Это работает только в том случае, если вы уже точно знаете, насколько глубоко вы находитесь в иерархии представлений. Более надежное и универсальное решение:

- (NSInteger)myRowNumber  
{   
    NSTableView* tableView = nil;   
    NSView* mySuperview = self;   

    do   
    {   
        NSView* nextSuper = mySuperview.superview;   
        if (nextSuper == nil)   
        {   
            NSException *exception =   
                [NSException exceptionWithName:@"NSTableView not found."   
                    reason:[NSString stringWithFormat:@"%@ search went too deep.",   
                    NSStringFromSelector(_cmd)] userInfo:nil];   
            @throw exception;   
        }   

        if ([nextSuper isKindOfClass:[NSTableView class]])   
            tableView = (NSTableView*)nextSuper;   
        else   
            mySuperview = mySuperview.superview;   
    } while (tableView == nil);   

    return [tableView rowForView:self];   
}   

это работает не только на уровне NSTableView, но и работает со всем, что установлено на любом уровне выше него, независимо от того, насколько сложна иерархия представлений.

Что касается оставшейся без ответа части вашего вопроса, я установил IBOutlet в своем классе и с помощью построителя интерфейса привязал его к владельцу моих файлов (в моем случае к моему классу документов). Получив ссылку на класс, которому я отправлял сообщение, и номер строки, я вызываю функцию. В моем случае вызов требовал, чтобы я передал номер строки, из которой он исходит.

[self.myDoc doSomethingToRow:self.myRowNumber];   

Я протестировал это, и оно работает на разных уровнях иерархии представлений выше NSTableView. И он работает без необходимости сначала выбирать строку (что, по-видимому, предполагается в документации Apple).

С уважением, Джордж Лоуренс Сторм, Мальтби, Вашингтон, США

person George Lawrence Storm    schedule 10.01.2013

Используйте rowForView: и цепочку респондентов

Чтобы отреагировать на действие элемента управления, встроенного в NSTableCellView, элемент управления должен выполнить действие для первого ответчика. В качестве альтернативы возможен Владелец файла, но он более тесно связан.

Используйте rowForView: в методе действия, чтобы определить, какая строка управление выдало действие:

- (IBAction)revealInFinder:(id)sender {
    NSInteger row = [self.tableView rowForView:sender];
    ...
}

Действие реализуется внутри любого из классов цепочки ответчиков. Скорее всего, это будет ваш подкласс NSWindowController. Ответчик также может быть делегатом приложения; если у делегата есть возможность поговорить с NSTableView.

См. пример Apple TableViewPlayground: Использование NSTableView и NSOutlineView на основе представлений, чтобы увидеть это. в действии.

person Graham Miln    schedule 30.11.2017

Ответ Suhas помог мне.

func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {

    if let cell = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "EDIT_CELL_VIEW"), owner: self) as? SymbolManagerCell  {                    
                if let editButton = cell.subviews[0] as? NSButton {
                    editButton.target = cell // this is required to trigger action
                }
                return cell
            }
    return nil
}
person Naren    schedule 04.03.2019