27 апр. 2014 г.

View-based NSTableView на основе ячеек из NSView (Злосчастная кнопка). Продолжение

В предыдущей статье о View-based NSTableView на основе ячеек из NSView не было реализации по использованию кнопки на виде (замечание в комментарии читателя). Порывшись в поиске (вместе с несуразными лексическими словосочетаниями), хоть какого-то решения так и не было найдено. Было решено использовать делегат и дать право AppDelegate кликать на эту злосчастную кнопку. 
Все бы ничего, но как узнать индекс этой чертовой вьюхи, на которой находится эта кнопка? Подумав, поломав голову вместе с мозгами, решил по нажатию кнопки AppDelegate-м передавать ему эту вьюху. Ведь все они разные, т.к. под каждую строку выделена память, естественно и адреса их будут разные.
Создаем делегат - добавляем в проект новый protocol-файл. Объявим в нем метод который будет передавать право тыканья этой кнопки AppDelegate-у.

#import <Foundation/Foundation.h>

@protocol ButtonControllerProtocol <NSObject>

@required
- (void) viewButtonClicked: (NSButton *) clickedButton view: (NSView *) viewCell;

@end

Далее в ViewController.h добавим экшен на кнопку, подключим AppDelegate и укажем какой метод использовать при нажатии этой кнопки.

- (IBAction)buttonInfo:(id)sender {
    
    AppDelegate *myAppDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
    [myAppDelegate viewButtonClicked:sender view:[self view]];
    
}

В AppDelegate.h подключим созданный протокол и пропишем делегат:

#import "ButtonControllerProtocol.h"

@interface AppDelegate : NSObject <NSApplicationDelegate, NSTableViewDelegate, NSTableViewDataSource, ButtonControllerProtocol> {

Реализуем протокольный метод:

- (void)viewButtonClicked: (NSButton *) clickedButton view: (NSView *) viewCell {
    NSLog (@"click");
}

Все бы хорошо, метод обрабатывается, выдает определенный результат, а дальше-то что? А дальше нам якобы нужно как-то менять данные на вьюхе. Вот здесь-то и пришлось помучатся. Хотя все оказалось немного проще. Мы помним что окно как главный вид, состоит из подвидов разной сложности, т.е. проще говоря на нашей вьюхе-подвиде тоже есть подвиды (subviews) - nsimageview, nstextfield и т.д. Остается лишь получить к ним доступ. Получим подвиды на вьхе-строке:


Загоним эти объекты в массив и потом создадим указатели на эти объекты и будем обращаться к непосредственно новым объектам-подвидам:

- (void)viewButtonClicked: (NSButton *) clickedButton view: (NSView *) viewCell {

    // Получаем строку-вид в нашей таблице
    NSView *clickedView = [clickedButton superview];
    
    // Получаем список подвидов в строке-виде
    NSArray *viewObjectsArray = [NSArray arrayWithArray:[clickedView subviews]];
    
    // Коннектимся к подвиду и задаем значение
    NSImageView *viewObjectImage = [viewObjectsArray objectAtIndex:0];
    [viewObjectImage setImage:[NSImage imageNamed:@"Slice 1"]];
    
    NSTextField *viewObjectFirstTextField = [viewObjectsArray objectAtIndex:1];
    [viewObjectFirstTextField setStringValue:@"Slice 1"];
    
}

Вот такое вот нетривиальное, не претендующее ни на что, решение. Если есть более человеческое решение - прошу указать в комментариях.

2 комментария:

  1. Отлично сработано! Единственное нужно учесть, что при создании interface порядок внесения элементов nsimageview, nstextfield, nsbutton и т.п. будет влиять на расположение элементов в массиве viewObjectsArray.

    ОтветитьУдалить
    Ответы
    1. Спасибо. Да, так и есть - при добавлении нового компонента на вьюху, порядок может немножко изменится. Но это не смертельно. Просто потратится некоторое время (один раз) на анализ порядка и идентификации этих объектов.

      Удалить