TableView mit NSArray durchsuchen

Dieses Thema im Forum "iOS-Developer" wurde erstellt von branco145, 03.06.10.

  1. branco145

    branco145 Rheinischer Winterrambour

    Dabei seit:
    26.07.09
    Beiträge:
    933
    Hallo,

    ich habe ein kleines App, der eine Tabelle mit Begriffen anzeigt, momentan noch aus einem NSArray.

    View1.h
    Code:
    #import <UIKit/UIKit.h>
    #import <Foundation/Foundation.h>
    
    @interface Dienstgrade : UIViewController /* Specify a superclass (eg: NSObject or NSView) */ {
    	NSArray *things;
    	IBOutlet UITableView *tableView;
    	
    }
    
    - (IBAction)back;
    
    @end
    
    Und in der .m Datei
    Code:
    #import "Dienstgrade.h"
    #import "DienstgradeDetailViewController.h"
    
    @implementation Dienstgrade
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    	things = [[NSArray alloc] initWithObjects:
    			  @"Schtz",
    			  @"Fu",
    			  @"Fig",
    			  @"Gren",
    			  @"Jg",
    			  @"Kan",
    			  @"Matr",
    			  @"Pi",
    			  @"PzFu",
    			  @"PzGren",
    			  @"PzJg",
    			  @"PzKan",
    			  @"PzPi",
    			  @"PzSchtz",
    			  @"PzSdt",
    			  @"Gefr",
    			  @"OGefr",
    			  @"HptGefr",
    			  @"StGefr",
    			  @"OStGefr",
    			  nil];
    }
    
    #pragma mark Table view methods
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
        return 1;
    }
    
    
    // Customize the number of rows in the table view.
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        return [things count];
    }
    
    
    // Customize the appearance of table view cells.
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        
        static NSString *CellIdentifier = @"Cell";
        
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
    		cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
        }
        
        
    	cell.text = [things objectAtIndex:indexPath.row];
        return cell;
    }
    
    
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
        DienstgradeDetailViewController *rdc = [[DienstgradeDetailViewController alloc] initWithNibName:@"RecipeDetailView" bundle:nil];
    	rdc.title = [things objectAtIndex:indexPath.row];
    	
    	
    	switch (indexPath.row) {
    		case 0:
    			rdc.rezeptText = @"Die Abkürzung 'Schtz' bedeutet Schütze.";
    			break;
    		case 1:
    			rdc.rezeptText = @"Die Abkürzung 'Fu' bedeutet Funker.";
    			break;
    		case 2:
    			rdc.rezeptText = @"Die Abkürzung 'Fig' bedeutet Flieger.";
    			break;
    		case 3:
    			rdc.rezeptText = @"Die Abkürzung 'Gren' bedeutet Grenadier.";
    			break;
    			
    		case 4:
    			rdc.rezeptText = @"Die Abkürzung 'Jg' bedeutet Jäger.";
    			break;
    		case 5:
    			rdc.rezeptText = @"Die Abkürzung 'Kan' bedeutet Kanonier.";
    			break;
    		case 6:
    			rdc.rezeptText = @"Die Abkürzung 'Matr' bedeutet Matrose.";
    			break;
    		case 7:
    			rdc.rezeptText = @"Die Abkürzung 'Pi' bedeutet Pionier.";
    			break;
    		case 8:
    			rdc.rezeptText = @"Die Abkürzung 'PzFu' bedeutet Panzerfunker.";
    			break;
    		case 9:
    			rdc.rezeptText = @"Die Abkürzung 'PzGren' bedeutet Panzergrenadier.";
    			break;
    		case 10:
    			rdc.rezeptText = @"Die Abkürzung 'PzJg' bedeutet Panzerjäger.";
    			break;
    		case 11:
    			rdc.rezeptText = @"Die Abkürzung 'PzKan' bedeutet Panzerkanonier.";
    			break;
    		case 12:
    			rdc.rezeptText = @"Die Abkürzung 'PzPi' bedeutet Panzerpionier.";
    			break;
    		case 13:
    			rdc.rezeptText = @"Die Abkürzung 'PzSchtz' bedeutet Panzerschütze.";
    			break;
    		case 14:
    			rdc.rezeptText = @"Die Abkürzung 'PzSdt' bedeutet Panzersoldat.";
    			break;
    		case 15:
    			rdc.rezeptText = @"Die Abkürzung 'Gefr' bedeutet Gefreiter.";
    			break;
    		case 16:
    			rdc.rezeptText = @"Die Abkürzung 'OGefr' bedeutet Obergefreiter.";
    			break;
    		case 17:
    			rdc.rezeptText = @"Die Abkürzung 'HptGefr' bedeutet Hauptgefreiter.";
    			break;
    		case 18:
    			rdc.rezeptText = @"Die Abkürzung 'StGefr' bedeutet Stabsgefreiter.";
    			break;
    		case 19:
    			rdc.rezeptText = @"Die Abkürzung 'OStGefr' bedeutet Oberstabsgefreiter.";
    			break;
    			
    		default:
    			break;
    			
    	}
    	
    	[self presentModalViewController:rdc animated:YES];
    	[rdc release];
    }
    
    
    - (IBAction)back {
    	
    	[self dismissModalViewControllerAnimated:YES];
    	
    	
    }
    
    
    @end
    
    
    Das Problem ist ja nun erstmal schon, das ich jeder Tabellenspalte einen festen Wert gegeben hab, so das wenn ich auf zeile 2 klicke auch Inhalt 2 auf dem DetailView angezeigt wird. Ich habe auch schon eine Suche implementiert gehabt, die funktionierte aber nicht, da ja jede Zeile ihren festen Wert hat, die sie im DetailView anzeigt. Das heißt ich suche nach "F" dann findet er alle Einträge mit F, ich klicke auf den ersten Eintrag und lande dann auf der DetailView, die zeigt mir dann aber den Wert an den ich ihr zuvor gegeben habe. Ich hoffe ihr versteht :eek:

    Wie kann ich also das NSArray so implementieren das ich nicht jeder Zeile den Wert festlegen muss, und eine Suche funktioniert?
     
  2. Poljpocket

    Poljpocket Salvatico di Campascio

    Dabei seit:
    07.01.07
    Beiträge:
    432
    Wenn du eine Suche ohne CoreData implementieren willst, musst du zwei NSArray deklarieren.

    Code:
    NSArray *dataArray = [[NSArray alloc] initWithObjects:{...}];
    NSMutable *filteredArray = [[NSMutableArray alloc] initWithArray:dataArray];
    Du füllst den filteredArray erstmal mit allen Einträgen aus dataArray, da das Suchfeld am Anfang noch leer ist -> alle Einträge sind enthalten.

    An das Suchfeld hängst du einen Controller an, der alle Änderungen mitkriegt (delegate) und der dann die Einträge im Array auf eine Zeichenfolge absucht. Jede Textänderung handelst du dann etwa so:

    Code:
    - (void)filterDidChange:(NSString *)searchText {
        [filteredArray removeAllObjects];
    
        for (NSString *value in dataArray) {
            if ([value rangeOfString:searchText].location != NSNotFound)
                 [filteredArray addObject:value];
        }
    
        [tableView reloadData];
    }
    So einfach hast du eine Suche für eine TableView.

    Du musst dann auch noch die dataSource-Methoden an das filteredArray anpassen.

    Gruss ppocket
     
    #2 Poljpocket, 03.06.10
    Zuletzt bearbeitet: 03.06.10
  3. branco145

    branco145 Rheinischer Winterrambour

    Dabei seit:
    26.07.09
    Beiträge:
    933
    Aber dann habe ich ja immer noch das Problem, wenn ich was suche, er z.B "A" findet und ich klicke dann Zeile "A" an dann komme ich auf Beschreibung "B" in der DetailView, weil ich die Zeilen ja fest definiert habe...

    Ich muss irgendwie Tabellenzeile "A", Beschreibung "A" auf der DetailView zuweisen ohne das auf eine bestimmte Zeile festzulegen.

    Das Video verdeutlicht das nochmal:
    http://www.youtube.com/watch?v=fJNs_EsNA7Q&feature=player_embedded

    Er nimmt auch in der Suche den festgelegten Eintrag und dann steht halt für "B" in der DetailView "T" statt "B". Er hat also die falsche Beschreibung in der DetailView.
     
    #3 branco145, 03.06.10
    Zuletzt bearbeitet: 03.06.10
  4. Poljpocket

    Poljpocket Salvatico di Campascio

    Dabei seit:
    07.01.07
    Beiträge:
    432
    Hier ein Beispielprojekt für die Suche, fertig implementiert. Da ich mich sonst mit UIKit nicht auskenne, weiss ich nicht, wie man diese doofe Tastatur dann wieder wegbringt... das musste selber rausfinden.

    Ich hab das so gelöst: Den Text, welcher auf der ModalView angezeigt werden soll, hab ich direkt in die Objekte geschrieben. Du machst also eine neue Klasse mit zwei Properties: Name und Beschreibung.

    Dann erstellst du deine Objekte mit dieser Klasse, füllst die Arrays mit diesen Objekten. So kannst du die Beschreibung des angeklicketen Objektes immer ganz einfach über die aktuelle Zeile herausfinden:

    Code:
    TableEntry *currentEntry = [filteredArray objectAtIndex:inIndexPath.row];
    So hast du immer sofort den Namen und die Beschreibung des aktuellen Items. Dies ist alles im Beispielprojekt enthalten. Schau es dir an!

    Gruss ppocket

    PS: So hast du eine eigene, kleine Datenbank erstellt. Das ist sowieso die Idee, dass du deine Daten speicherst und dann schlau anzeigst. Es ist sehr ineffizient, wie du das gelöst hast. Ich mit meinem Beispiel könnte meine Daten mit meiner Struktur einfach aus einer Datei rauslesen und das am Anfang des Programmes. Dann die Datei links liegen lassen und das Programm einfach machen lassen. Du müsstest jedes Mal wieder auf die Datei zugreifen, da du die Beschreibungen deiner Dienstgrade nirgendwo speicherst, sondern sie statisch im Quellcode selber definierst. Das ist gar nicht die Idee!
     

    Anhänge:

    #4 Poljpocket, 03.06.10
    Zuletzt bearbeitet: 03.06.10
  5. branco145

    branco145 Rheinischer Winterrambour

    Dabei seit:
    26.07.09
    Beiträge:
    933
    Danke dir, funktioniert perfekt.
     
  6. Poljpocket

    Poljpocket Salvatico di Campascio

    Dabei seit:
    07.01.07
    Beiträge:
    432
    lol... ich setz mich 20 Minuten hinter den Mac und schreibe dir ein Beispielprojekt und du lädst es nicht mal runter. haha, nene, kein Problem! :)
     
  7. branco145

    branco145 Rheinischer Winterrambour

    Dabei seit:
    26.07.09
    Beiträge:
    933
    Und wie krieg ich es noch hin, das statt des Popups eine neue View angezeigt wird (DetailView)?
     
  8. branco145

    branco145 Rheinischer Winterrambour

    Dabei seit:
    26.07.09
    Beiträge:
    933
  9. branco145

    branco145 Rheinischer Winterrambour

    Dabei seit:
    26.07.09
    Beiträge:
    933
  10. branco145

    branco145 Rheinischer Winterrambour

    Dabei seit:
    26.07.09
    Beiträge:
    933
    *push*

    Und wie krieg ich es noch hin, das statt des Popups eine neue View angezeigt wird (DetailView)?
     
  11. branco145

    branco145 Rheinischer Winterrambour

    Dabei seit:
    26.07.09
    Beiträge:
    933
    Einer muss es doch wissen...?
     
  12. Zettt

    Zettt Doppelter Melonenapfel

    Dabei seit:
    16.10.05
    Beiträge:
    3.374
    Scheinbar nicht. Was haeltst du davon wo anders zu fragen?
     
  13. Poljpocket

    Poljpocket Salvatico di Campascio

    Dabei seit:
    07.01.07
    Beiträge:
    432
    Na genau so, wie du es in deinem Code hast!

    Gruss ppocket

    Sent from my HTC Desire using Tapatalk
     
  14. Drobs

    Drobs Carola

    Dabei seit:
    23.05.08
    Beiträge:
    115
    Ohne mir das Projekt angeguckt zu haben, gehe ich davon aus, dass Poljpocket einen ModalView benutzt hat.

    Das heißt, dass iwo eine Zeile ähnlich dieser steht:

    Code:
    [self presentModalViewController:MeinUIViewController animated:YES];
    welche du, wenn du einen NavigationController hast, durch folgende Zeile ersetzen kannst:

    Code:
    [self.navigationController pushViewController:MeinUIViewController animated:YES];

    Nebenbei würde es sicher helfen, wenn du selber mal dein Hirn anstrengst und dich mit Hilfe von Google auf die Suche nach einer Lösung machst. Das sollte nämlich ohne weiteres möglich sein.
     
  15. Poljpocket

    Poljpocket Salvatico di Campascio

    Dabei seit:
    07.01.07
    Beiträge:
    432
    Er muss nichts mehr überlegen oder suchen. Ich habe nur die dataSource für seine Tabelle verändert und an das Datenmodell angepasst. Er muss in der Methode, wo die Selektion abgefangen wird, nur seinen eigenen Code einfügen und es funktioniert. Ich hab das halt mit einem Alert gelöst, da ich nicht noch extra eine weitere Subklasse erstellen wollte.

    Gruss ppocket
     
  16. Zettt

    Zettt Doppelter Melonenapfel

    Dabei seit:
    16.10.05
    Beiträge:
    3.374
  17. Poljpocket

    Poljpocket Salvatico di Campascio

    Dabei seit:
    07.01.07
    Beiträge:
    432
    Nein, um das gehts nicht... er hat ja in seinem Code genau (und auch richtig) geschrieben, wie der DetailView Controller angezeigt wird. Er muss diesen Code nur noch kopieren und an mein Datenmodell anpassen. Ganz einfach...

    Gruss ppocket
     
  18. Poljpocket

    Poljpocket Salvatico di Campascio

    Dabei seit:
    07.01.07
    Beiträge:
    432
    Hier also nochmal das Beispielprojekt erweitert:

    - Anzeige per ModalViewController

    Gruss ppocket
     

    Anhänge: