objective-c cocoa nstableview

objective c - Cómo crear una acción a partir de la selección de una fila de un NSTableView



objective-c cocoa (5)

Cuando selecciono una fila de NSTableView , no se está ejecutando el código del método tableViewSelectionDidChange . Yo había puesto puntos de quiebre en este método y ni siquiera está entrando en el método.

¿Algunas ideas? ¿Me estoy perdiendo algo en mi inicializador?

PersonController.h

#import <Foundation/Foundation.h> @interface Person : NSObject { IBOutlet NSTableView *personsTable; NSMutableArray *personsList; NSMutableArray *personCollection; IBOutlet NSTextField *selectedPersonName; IBOutlet NSTextField *selectedPersonGender; @private } - (void)tableViewSelectionDidChange:(NSNotification *)aNotification; @end

PersonController.m

#import "PersonController.h" #import "Person.h" @implementation PersonController - (id)init { self = [super init]; if (self) { personsList = [[NSMutableArray alloc] init]; Person *person = [[Person alloc] init]; // Create person 1 person.name = @"Bob"; person.gender = @"male"; // Append to array [personsList addObject:person]; [person release]; // Create person 2 person = [[Person alloc] init]; person.name = @"Fred"; person.gender = @"Unknown"; // Append to array [personsList addObject:person]; [person release]; [personsTable reloadData]; } return self; } - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { return [personsList count]; } - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { Person *person = [personsList objectAtIndex:row]; NSString *identifier = [tableColumn identifier]; return [person valueForKey:identifier]; } - (void)tableViewSelectionDidChange:(NSNotification *)aNotification { NSInteger selectedRow = [personsTable selectedRow]; if (selectedRow == -1) { // these should be localized, but use string constants here for clarity [selectedPersonName setStringValue:@"No selection"]; [selectedPersonGender setStringValue:@"No selection"]; } else { Person *selectedPerson = [personCollection objectAtIndex:selectedRow]; [selectedPersonName setStringValue:[selectedPerson name]]; [selectedPersonGender setStringValue:[selectedPerson gender]]; } } - (void)dealloc { [super dealloc]; } @end


Así que el problema aquí fue que estaba tratando de usar tableViewSelectionChange para desencadenar un evento cuando se hacía clic en una fila en NSTableColumn. Como no pude hacer que funcionara, IBAction otro enfoque: crear una IBAction y vincular esto con el NSTableView, y encontré que esto funciona bien.

Para hacer esto, hice lo siguiente:

  1. Eliminar - (void)tableViewSelectionDidChange
  2. Crear IBAction
  3. En el archivo XIB, cree un enlace de Received Actions entre IBAction y NSTableView, en el inspector de conexiones de NSTableView en "acción enviada" haga que "selector" accione "conecte este" selector "con la IBAction que desea activar.

Esta es la IBAction en PersonController.m

- (IBAction)columnChangeSelected:(id)sender { NSInteger selectedRow = [personsTable selectedRow]; if (selectedRow != -1) { NSLog(@"Do something with selectedRow!"); } else { // No row was selected } }


Asegúrese de que la instancia de PersonController esté conectada a personsTable como delegado . No sé cómo creó NSTableView, pero si está utilizando Nibs, puede configurar el delegado en Interface Builder. Si no, puede agregar [personsTable setDelgate:self] en el método init y [personsTable setDelegate:nil] en el método dealloc .

Además, estás perdiendo personasLista. Agregue [personsList release] a su método de delegado.


Para ampliar la respuesta de Coderama, el equivalente en código es:

tableView.target = self; tableView.action = @selector(tableViewClicked:);

Luego implementa el método en la misma clase:

- (void)tableViewClicked:(id)sender { // This will return -1 if the click did not land on a row NSLog(@"tableView.clickedRow = %ld", tableView.clickedRow); // This will return -1 if there is no row selected. NSLog(@"tableView.selectedRow = %ld", tableView.selectedRow); }

La vista de tabla llamará a su método de acción en el destino que establezca cada vez que se haga clic en la vista. Esto le permitirá saber cada vez que se selecciona una fila, incluso si ya está seleccionada.


Para otros que se topan con este problema: otra razón para que no se llame a este delegado podría ser porque la fila ya está seleccionada. Así que no se notificará a menos que se haga una nueva selección. Si aún desea poder recibir notificaciones en cada clic, deseleccione todas las filas una vez que se le notifique.

Ahora esto hará 2 llamadas a su delegado, una para ser seleccionado y otra para ser deseleccionado. La segunda llamada no es necesaria, así que agregue una condición en la parte superior para verificar [tableView selectedRow] esto devolvería -1 cuando no se seleccionan filas.


Solución en Swift 3 para la mayoría de los eventos:

Controlador de vista de tableview interior:

override func viewDidLoad() { super.viewDidLoad() tableView.target = self tableView.action = #selector(tableViewDidClick) } func tableViewDidClick(){ let row = tableView.clickedRow let column = tableView.clickedColumn let unselected = -1 if row == unselected && column == unselected{ tableViewDidDeselectRow() return }else if row != unselected && column != unselected{ tableViewDidSelectRow(row) return }else if column != unselected && row == unselected{ tableviewDidSelectHeader(column) } } private func tableViewDidDeselectRow() { // clicked outside row } private func tableViewDidSelectRow(_ row : Int){ // row did select } private func tableviewDidSelectHeader(_ column : Int){ // header did select }