2012-02-04 10 views
16

Po wybraniu wiersza z NSTableView, nie jest on uruchomiony z metody tableViewSelectionDidChange. Wprowadziłem przełom w tej metodzie, a nawet nie wchodzę w tę metodę.Jak utworzyć akcję po wybraniu wiersza z NSTableView

Wszelkie pomysły? Czy brakuje mi czegoś w moim inicjatorze?

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

wierzę tableViewSelectionDidChange nie był nazywany, ponieważ nie zaszło delegata Twojego NSTableView za. –

Odpowiedz

27

Problem polegał na tym, że próbowałem użyć tableViewSelectionChange, aby wywołać zdarzenie po kliknięciu wiersza w kolumnie NSTableColumn. Ponieważ nie mogłem uzyskać tego działającego podjąłem inne podejście, które było stworzenie IBAction i link do NSTableView i znalazłem to działa dobrze.

Aby to zrobić, zrobiłem, co następuje:

  1. Usuń - (void)tableViewSelectionDidChange
  2. Tworzenie IBAction
  3. W pliku XIB utwórz Received Actions związek między IBAction i NSTableView, w związku NSTableView inspektor w sekcji "wysłana czynność" ma działanie "selektora" "połącz ten" selektor "z tą IBAction, którą chcesz wywołać:

jest IBAction w PersonController.m

- (IBAction)columnChangeSelected:(id)sender 
{ 
    NSInteger selectedRow = [personsTable selectedRow]; 

    if (selectedRow != -1) { 
     NSLog(@"Do something with selectedRow!"); 
    } 
    else { 
     // No row was selected 
    } 
} 
2

Upewnij się, że wystąpienie PersonController jest podłączony do personsTable jako delegata. Nie wiem, jak stworzyłeś NSTableView, ale jeśli używasz Stalówek, możesz ustawić delegata w Konstruktorze Interfejsu. Jeśli nie, można dodać metodę [personsTable setDelgate:self] w metodzie init i [personsTable setDelegate:nil] w metodzie dealloc.

Ponadto, jesteś nieszczelny osóbLista. Dodaj [personsList release] do metody delegatów.

+0

Instancja PersonController jest już połączona z osobą persons jako delegatem. Dziękuję za to, że zauważyłem wycieki osób. – Coderama

2

Dla innych, którzy wpadają na ten problem: inny powód tego delegata nie miano może być dlatego, że rząd jest już wybrany. Więc nie powiadomi, chyba że zostanie dokonany nowy wybór. Jeśli nadal chcesz otrzymywać powiadomienia za każdym kliknięciem, odznacz wszystkie wiersze po otrzymaniu powiadomienia.

Teraz będzie to 2 połączenia z twoim uczestnikiem, jeden do uzyskania wybranego i inny do uzyskania odznaczenia. Drugie wywołanie nie jest potrzebne, więc dodaj warunek na górze, aby sprawdzić [tableView selectedRow], który zwróci -1, gdy nie zostaną wybrane żadne wiersze.

3

Aby rozwinąć na odpowiedź Coderama za ekwiwalent w kodzie jest:

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

następnie wdrożyć metody w tej samej klasie:

- (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); 
} 

Widok tabela wywołać jej metody działania na tarczy ustawiasz za każdym kliknięciem widoku. Dzięki temu będziesz wiedzieć za każdym razem, gdy wybrany zostanie wiersz, nawet jeśli jest już wybrany.

1

Rozwiązanie w Swift 3 dla większości zdarzeń:

Wewnątrz tableview kontroler widok:

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 
} 
Powiązane problemy