Hallo erstmal, ich bin neuling in diesem forum und habe auch gleich schon eine frage.
Mein vorhaben:
Ich habe ein Textfield und gebe dort einen int wert ein Z.b. 5... Ist es möglich dass mir daraus 5 grouped cell sections erstellt werden mit jeweils 3 rows?
TableViewCell Sections
-
-
Gibbson schrieb:
Hallo erstmal, ich bin neuling in diesem forum und habe auch gleich schon eine frage.
Mein vorhaben:
Ich habe ein Textfield und gebe dort einen int wert ein Z.b. 5... Ist es möglich dass mir daraus 5 grouped cell sections erstellt werden mit jeweils 3 rows?
Klar, musst die Datasource der TableView anpassen, nachdem der Wert eingetragen wurde und die TableView reloaden -
Hallo, danke erstmal!
ich habe es geschafft dass mir soviele sections angezeigt werden wie ich vorher in einem anderen viewcontroller angegeben habe.
ich schaffe es aber nicht, dass je section die cell atindex:0 durch cell atindex:1 geteilt wird.
der code ist folgender:
Alles anzeigenQuellcode
- #import "ViewController.h"
- @interface ViewController ()
- {
- NSMutableArray *sectionsArray;
- NSMutableArray *rowsInSectionsArray;
- }
- @end
- @implementation ViewController
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- // Do any additional setup after loading the view, typically from a nib.
- [[self myTableView]setDelegate:self];
- [[self myTableView]setDataSource:self];
- sectionsArray = [[NSMutableArray alloc]init];
- rowsInSectionsArray = [[NSMutableArray alloc]init];
- }
- - (void)didReceiveMemoryWarning
- {
- [super didReceiveMemoryWarning];
- // Dispose of any resources that can be recreated.
- }
- - (IBAction)addSectionButton:(id)sender {
- [sectionsArray addObject:[NSString stringWithFormat:@"Palette %d",sectionsArray.count+1]];
- [[self myTableView]reloadData];
- }
- - (IBAction)rechneButton:(id)sender {
- }
- #pragma datasource tableview methods
- -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
- {
- int anzahl = [_AnzahlStationen intValue];//aus dem text wird ein int gemacht
- //fügt soviele sections ein wie vorher eingegeben
- if ([sectionsArray count] < anzahl) {
- [sectionsArray addObject:[NSString stringWithFormat:@"Palette %d",sectionsArray.count+1]];
- [[self myTableView]reloadData];//tableview wird aktualisiert
- }
- return sectionsArray.count;
- /*if (sectionsArray.count == 0) {
- [sectionsArray addObject:[NSString stringWithFormat:@"Palette %d",sectionsArray.count+1]];
- }
- return sectionsArray.count;
- */
- }
- -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
- {
- return 3;
- }
- -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
- {
- return [sectionsArray objectAtIndex:section];
- }
- -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- {
- static NSString *CellIdentifier = @"Cell";
- UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
- if(!cell)
- {
- cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
- cell.selectionStyle = UITableViewCellSelectionStyleNone;
- //Textfelder innerhalb der cells
- UITextField *textfelder = [[UITextField alloc] initWithFrame:CGRectMake(15, 10, 185, 30)];
- [textfelder setFont:[UIFont fontWithName:@"Gujarati Sangam MN" size:14]];
- [textfelder setTextColor:[UIColor blueColor]];
- [[cell contentView] addSubview:textfelder];
- if ([indexPath row] == 0) {
- textfelder.placeholder = @"Bogen auf Palette";
- }
- if ([indexPath row] == 1) {
- textfelder.placeholder = @"Stangen auf Palette";
- }
- if ([indexPath row] == 2) {
- textfelder.placeholder = @"...oder Bogen auf Stange";
- }
- }
- return cell;
- }
- @end
-
Hmm. Ich würde in meiner Klasse vielleicht das UITextFieldDelegate Protokoll implementieren und self als den delegate an den Textfeldern setzen. Zum Unterscheiden kannst Du ja Tags an die Textfelder setzen, damit Du weißt, welches Feld gerade einen neuen Wert bekommen hat.
Beim Berechnen greifst Du dann nicht auf die Textfelder zu, sondern auf die lokal gespeicherten Daten (die Du Dir beim Aufruf der TextFieldDelegate Methode gemerkt hast).
Denke immer dran, dass TabelViewCells neu genutzt werden. Also wenn Du einen Teil der TableView aus dem Bildschirm scrollst, sind die Textfelder weg und werden neu genutzt. Das kann auch jetzt schon passieren, wenn Du im ersten Feld mal etwas einträgst und dann die Tabelle soweit hoch scrollst, dass das Textfeld verschwindet. Wenn es wieder kommt, kann es sein, dass der Wert, den Du vorher eingegeben hast, wieder weg ist oder irgendeiner alten Eingabe entspricht.
Deswegen hat man zur reinen Repräsentation in der TableView immer noch ein Datenmodel im Hintergrund, dass die eigentlichen Objekte (bei Dir die Zahlen) speichert. Du könntest dafür ja ein Array mit Arrays von Zahlen nehmen.
Oder so ähnlich. -
Ach, und bei [UITableView reloadData] innerhalb einer TableViewDataSource Methode zucke ich intuitiv zusammen. Ich glaube das ist keine gute Idee. Offenbar funktioniert das ja, ich hätte da aber Angst vor einer möglichen Endlosschleife.
Berechnungen zur Anzahl der Sektionen solltest Du außerhalb der TableViewDataSource Methoden machen. Zum Beispiel in viewWillAppear. -
Vielen dank ! Für mich ist es nicht so einfach deine vorschläge in die tat umzusetzen. Ich bin erst seit kurzem dabei objective c zu erlernen. Da sind so einige glückstreffer dabei mit viel rumprobieren
-
Dann fang doch erstmal einfacher an: nur eine Sektion, eine Zelle und darin ein Textfield.
Dann nimmst Du eine Membervariable in Deinen ViewController hinzu, die den Wert im Textfeld repräsentiert (später macht man sich dann eigene Model-Klassen für sowas).
Im tableView:cellForRowAtIndexPath: weist Du dem Textfeld den Wert Deiner Membervariablen zu.
Im textFieldDidEndEditing: liest Du den vom Benutzer eingegebenen Wert aus und merkst ihn Dir wieder in Deiner Membervariable (Deinem "Model für Arme").
Im rechneButton:sender: greifst Du dann gar nicht auf die TableViewCell oder das Textfield zu, sondern rechnest einfach mit Deiner Membervariablen. Als allererstes schreibst Du da nur NSLog(@"%@", Membervariable); rein, um zu kontrollieren dass die ganze Kette funktioniert.
Danach nimmst Du dann mehrere Textfelder in die eine Sektion - dabei musst Du Dir überlegen, wie Du die Textfelder voneinander unterscheidest. Da gibt es mehrere Varianten, aber soweit bist Du ja noch nicht. Erstmal ein Textfeld. Und jetzt los!
-
Ich habe mir Deinen Rat zu Herzen genommen und habe erstmal nur eine section mit einer row erstellt.
Jetzt weiss ich nicht wie ich das Textfield erstelle, ohne dass es beim (aus dem bild scrollen) die Daten durcheinander wirft.
Alles anzeigenQuellcode
- #import "ViewController.h"
- @interface ViewController ()
- {
- NSMutableArray *sectionsArray;
- }
- @end
- @implementation ViewController
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- [[self meinTableView]setDelegate:self];
- [[self meinTableView]setDataSource:self];
- sectionsArray = [[NSMutableArray alloc]init];
- }
- - (void)didReceiveMemoryWarning
- {
- [super didReceiveMemoryWarning];
- // Dispose of any resources that can be recreated.
- }
- - (IBAction)erstelleSectionsButton:(id)sender {
- }
- -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
- {
- do {
- [sectionsArray addObject:[NSString stringWithFormat:@"Palette %d",sectionsArray.count+1]];
- } while (sectionsArray.count < 1);
- return sectionsArray.count;
- }
- -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
- {
- return [sectionsArray objectAtIndex:section];
- }
- -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
- {
- return 1;
- }
- -(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- {
- static NSString *CellIdentifier = @"Cell";
- UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
- if(!cell)
- {
- cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
- cell.selectionStyle = UITableViewCellSelectionStyleNone;
- }
- return cell;
- }
- @end
-
Öhm. Ich sehe da gar kein UITextField im Code ...
Aber wie gesagt: der "Trick" ist, dass Du eine extra Membervariable für den Inhalt des Textfeldes in dem ViewController hast.
In cellForRowAtIndexPath bekommt die neue Zelle ein TextField und den Text des Feldes füllst Du mit dem Wert der Membervariablen. So steht dort immer das richtige drin.
Hast Du denn schon etwas über textFieldDidEndEditing gelesen? Dort holst Du den vom Benutzer eingegebenen Wert wieder aus dem Textfeld heraus und frischst Deine Membervariable damit auf. -
nun habe ich in der h datei die variable deklariert...
das textfield habe ich eingefügt und es der variablen zugewiesen, hoffe dass es so richtig ist!?
Alles anzeigenQuellcode
- -(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- {
- static NSString *CellIdentifier = @"Cell";
- UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
- if(!cell)
- {
- cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
- cell.selectionStyle = UITableViewCellSelectionStyleNone;
- UITextField *textfeld = [[UITextField alloc] initWithFrame:CGRectMake(15, 10, 185, 30)];
- [textfeld setFont:[UIFont fontWithName:@"Gujarati Sangam MN" size:14]];
- [textfeld setTextColor:[UIColor blueColor]];
- [[cell contentView] addSubview:textfeld];
- _bogenAufPalette = textfeld.text;
- }
- return cell;
- }
-
So in etwa würde ich das auch machen. Ich hab parallel mal schnell das hier gebaut:
Alles anzeigenQuellcode
- @interface MasterViewController ()
- @property NSInteger value;
- @end
- @implementation MasterViewController
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- self.value = 7;
- }
- - (void)viewWillAppear:(BOOL)animated
- {
- [super viewWillAppear:animated];
- [self.tableView reloadData];
- }
- #pragma mark - Table View
- - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
- {
- return 1;
- }
- - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
- {
- return 1;
- }
- - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- {
- UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
- if (!cell) {
- cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
- UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10, 10, 300, 24)];
- textField.autoresizingMask = UIViewAutoresizingFlexibleWidth;
- textField.tag = 17;
- [cell.contentView addSubview:textField];
- textField.delegate = self;
- }
- UITextField *textField = (UITextField *)[cell.contentView viewWithTag:17];
- textField.text = [NSString stringWithFormat:@"%d", self.value];
- return cell;
- }
- #pragma mark - UITextFieldDelegate
- - (BOOL)textFieldShouldReturn:(UITextField *)textField
- {
- [textField resignFirstResponder];
- return YES;
- }
- - (void)textFieldDidEndEditing:(UITextField *)textField
- {
- self.value = [textField.text integerValue];
- }
- @end
Sicher hat jeder noch seine künstlerische Freiheit, aber Du siehst mal grundsätzlich das Konzept. -
Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von Gibbson ()
-
Da liegt der Trick in der Header-Datei des ViewControllers:
Das Ding in den spitzen Klammern sagt: "Ja, also, ich hier, ich implementiere die Methoden dieses Protokolls" - und dann kann ein Objekt dieser Klasse überall genutzt werden, wo das Protokoll eben gesprochen wird. Zufällig verschwindet dann auch der Fehler (der eigentlich nur eine Warnung ist).
-
Ok, also soweit habe ich das glaube ich verstanden. Die Variable value übernimmt jetzt den Wert des Textfeldes.
Ich habe jetzt mehrere sections eingefügt mit je 4 rows und es wird logischerweise in jedem Textfeld immer der gleiche Wert angezeigt, nämlich der von value.
Nachdem ich die ganze Woche herumprobiert habe es irgendwie durch "Nachforschung im Internet" hinzubekommen die Werte in ein NSMutableArray einzufügen und wieder herauszuholen...brauche ich wohl doch noch ewas Hilfe. -
Na schreib doch mal die entscheidenden Zeilen Code hier rein und sag an, was genau nicht geht.
-
Ich möchte ja das valueArray nach dem editieren mit dem Text füllen...
Das Problem ist nun aber dass ich erstmal ein leeres Array habe und der Simulator abstürzt, da ich ja hier sage dass das Textfeld seinen Text aus dem Array nehmen soll.
Alles anzeigenQuellcode
- - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- {
- UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
- if (!cell) {
- cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
- UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10, 10, 300, 24)];
- textField.autoresizingMask = UIViewAutoresizingFlexibleWidth;
- textField.tag = 17;
- [cell.contentView addSubview:textField];
- textField.delegate = self;
- }
- UITextField *textField = (UITextField *)[cell.contentView viewWithTag:17];
- textField.text = [valueArray objectAtIndex:indexPath.row];
- return cell;
- }
Wenn ich folgendes versuche...
...erstellt er mir zu den 4 rows eine weitere row samt eingegebenen Text. -
Na dann sind wir ja schon an der entscheidenden Stelle angekommen: dem Datenmodell.
Das Datenmodell gibt es immer, auch wenn der Benutzer noch nichts eingegeben hat. Das Datenmodell ist immer konsistent. Das heißt in Deinem Fall, dass Dein Datenmodell (also das MutableArray) schon gleich am Anfang vier Zahlen enthält. Wenn ein Leerzeichen in Deinem Datenmodell auch erlaubt ist, dann musst Du Zeichenketten speichern und nicht Zahlen und dann im Moment der Berechnung erst aus den Zeichenketten die Zahlen extrahieren.
Also:
1.) im viewDidLoad das Array mit vier ordentlichen Werten initialisieren
2.) in cellForRowAtIndexPath den Wert aus dem Array holen (machst Du ja schon ordentlich)
3.) in textFieldDidEndEditing
3.a) erstmal heraus bekommen, welches Feld gerade editiert wurde
3.b) den neuen Wert an die richtige Stelle des MutableArrays schreiben - und zwar nicht mit addObject (das hängt immer hinten an), sondern mit replaceObjectAtIndex:withObject: oder setObject:atIndexedSubscript: (Achtung! Die Methode gibt es erst ab iOS 6)
Das Datenmodell repräsentiert "im Hintergrund" das, was der Benutzer "im Vordergrund" sieht. Ich würde z.B. in tableView:numberOfRowsInSection: gar nicht fest 4 zurück geben, sondern [rowsArray count] - das stimmt immer, selbst wenn Du danach einfach mal mit 5 oder 7 Werten testest. Nur rowsArray muss von Anfang an die richtige Zahl Elemente haben.
Es gibt bestimmt auch noch andere Wege, jeder der sonst hier im Forum unterwegs ist, wird das irgendwie anders lösen. Aber programmieren ist ja auch kreative Arbeit. Ich hätte zu 3.a gerade gar keine so richtig schöne Lösung. Man könnte das Tag der TextViews immer um eins hoch zählen und dann wieder zurück rechnen. Aber das fühlt sich komisch an. So eine blitzsaubere Idee habe ich da noch gar nicht. Du siehst ... man lernt immer noch irgendwas ...
-