2012-02-04 19 views
16

Cuando selecciono una fila desde NSTableView, no se está ejecutando el código del método tableViewSelectionDidChange. Había puesto puntos de ruptura en este método y ni siquiera está entrando en el método.Cómo crear una acción desde la selección de una fila desde un NSTableView

¿Alguna idea? ¿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 
+0

Creo tableViewSelectionDidChange no estaba siendo llamado, porque no se había fijado delegado de su NSTableView. –

Respuesta

27

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

Con el fin de hacer esto, hice lo siguiente:

  1. Eliminar - (void)tableViewSelectionDidChange
  2. Crear IBAction
  3. En el archivo XI ter, crear un enlace Received Actions entre el IBAction y la NSTableView, en relación NSTableView inspector en "acción enviada" tiene "selector" acción "conectar este" selector "con esa IBAcción que desea activar.

Esto 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 
    } 
} 
2

Asegúrese de que la instancia de PersonController está conectado a personsTable como el delegado . No sé cómo creó NSTableView, pero si está usando 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, usted es fugas personsList. Agregue [personsList release] a su método delegado.

+0

La instancia de PersonController ya está conectada a personsTable como delegado. Gracias por detectar la fuga de personas. – Coderama

2

Para otros que toparse con este tema: otra razón para este delegado no ser llamado podría ser debido a la fila ya está seleccionada. Por lo tanto, no se notificará a menos que se realice una nueva selección. Si aún desea recibir notificaciones en cada clic, anule la selección de todas las filas una vez que reciba una notificación.

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 seleccionen las filas.

3

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

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

luego implementar el método de 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 objetivo usted configura cada vez que se hace clic en la vista. Esto le permitirá saber cada vez que se selecciona una fila, incluso si ya está seleccionada.

1

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

Dentro tableview controlador de vista:

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 
} 
Cuestiones relacionadas