2012-02-23 19 views
7

Ho un UITableView con 8 celle (sezioni) in totale, di cui 6 contengono campi di testo come sottoview e di 2 un pulsante contenente e l'altro contenente la vista di testo. Ora ho un problema qui, dato che siamo tutti consapevoli del fatto che quando la vista appare solo, le celle visibili si caricano. Così quando viene caricata la mia app, sono in grado di visualizzare 5 celle, i primi 4 contenenti campi di testo e la quinta cella con il pulsante. può vedere il conteggio matrice è 4 quando visualizzato tramite registrazione in console cioèCaricare tutte le celle in UITableView prima di scorrere

there are 4 objects in the array 

Ora dopo lo scorrimento visualizzazione tabella, posso osservare quanto segue:

there are 6 objects in the array 

Quindi, cosa succede è che se devo salvare i dati inseriti nella vista tabella, o dire modifica per apportare modifiche ai dati esistenti, sono costretto a scorrere la vista tabella e inserire i valori anche nell'ultima cella. Quindi questo non può essere il caso sempre con l'utente, perché non possiamo aspettarci che lui/lei faccia scorrere la vista tabella e inserisca le voci di cella complete della vista tabella/modulo. Che cosa cambierà lui/lei farà e basta fare clic su Fatto/salva cosa mai lo è ..!

Più oltre Ho una vista di selezione come vista di input per l'ultima cella contenente il campo di testo come subview.Hence nella mia vista di selezione ha selezionato il metodo di riga I si trovano ad affrontare il problema di crash con l'ultima cella/sezione (textField come sottoview) contenente un vista picker ecco il mio frammento di codice per il metodo:

-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component 
{ 

    switch (tagValues) 
    { 

     case 105: 
     { 
      self.textField = [self.fields objectAtIndex:3]; 
      self.textField.text = [self.reminder objectAtIndex:row]; 
     } 
      break; 

     case 107: 
     { 
      //Crash occurring in this case,sometimes its working wonder why 
      self.textField = [self.fields objectAtIndex:5]; 
      self.textField.text = [self.group objectAtIndex:row]; 
     } 
      break; 

    } 

} 

**Note**:I am using the same textField for adding as subview to all 6 cells,but each one with unique tags and own purpose,i.e. one for editing text using key board,one with date picker,one with general picker etc... 

mi chiedo perché alcune volte dopo si seleziona un valore dal punto di vista picker (ultima cella di sezione) si blocca a volte e alcune volte funziona fine.Some volte si blocca al di sopra linea commentata nel caso , alcune volte nel pool principale di autorelease.Alcune sequenze di tempo come mostrato nello snap qui sotto:

enter image description here

Quindi non v'è alcun modo che siamo in grado di caricare tutte le cellule in una sola volta in modo che tutti i campi di testo vengono aggiunti alla matrice prima scrolling.There non può essere alcun problema credo

più dettagliata EDITED CODICE per la comprensione:

- (UITableViewCell *)tableView:(UITableView *)atableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 

    //NSString *identifier = @"UITableViewCell"; 

    NSString *cellIdentifierF = nil; 

    static NSString *firstCellIdentifier = @"FirstCell"; 
    static NSString *secondCellIdentifier = @"SecondCell"; 
    static NSString *thirdCellIdentifier = @"ThirdCell"; 
    static NSString *fourthCellIdentifier = @"FourthCell"; 
    static NSString *fifthCellIdentifier = @"FifthCell"; 
    static NSString *sixthCellIdentifier = @"SixthCell"; 
    static NSString *seventhCellIdentifier = @"SeventhCell"; 
    static NSString *eightCellIdentifier = @"EightCell"; 

    if(indexPath.section == 0 && indexPath.row == 0) 
    { 
     cellIdentifierF = firstCellIdentifier; 
    } 
    else if(indexPath.section == 1 && indexPath.row == 0) 
    { 
     cellIdentifierF = secondCellIdentifier; 
    } 
    else if(indexPath.section == 2 && indexPath.row == 0) 
    { 
     cellIdentifierF = thirdCellIdentifier; 
    } 
    else if(indexPath.section == 3 && indexPath.row == 0) 
    { 
     cellIdentifierF = fourthCellIdentifier; 
    } 
    else if(indexPath.section == 4 && indexPath.row == 0) 
    { 
     cellIdentifierF = fifthCellIdentifier; 
    } 
    else if(indexPath.section == 5 && indexPath.row == 0) 
    { 
     cellIdentifierF = sixthCellIdentifier; 
    } 
    else if(indexPath.section == 6 && indexPath.row == 0) 
    { 
     cellIdentifierF = seventhCellIdentifier; 
    } 
    else if(indexPath.section == 7 && indexPath.row == 0) 
    { 
     cellIdentifierF = eightCellIdentifier; 
    } 

    UITableViewCell *cell = (UITableViewCell *)[atableView dequeueReusableCellWithIdentifier:cellIdentifierF]; 

     atableView.backgroundColor = [UIColor clearColor]; 

     textField = [[[UITextField alloc]initWithFrame:CGRectMake(15, 12, 300, 24)]autorelease]; 
     textField.textColor = [UIColor whiteColor]; 
     textField.delegate = self; 
     tagValues = textField.tag; 

    switch (indexPath.section) 
    { 
     case 0: 
     { 
      if (cell == nil) 
      { 
       cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifierF] autorelease]; 
       cell.backgroundColor = [[UIColor alloc]initWithPatternImage:[UIImage imageNamed:@"buttonbg-1.png"]]; 

       //Only add content to cell if it is new 
       if([cellIdentifierF isEqualToString: firstCellIdentifier]) 
       { 
        textField.placeholder = @"Enter name"; 
        [self.textField setValue:[UIColor purpleColor] 
            forKeyPath:@"_placeholderLabel.textColor"]; 
        textField.tag = 101; 
        textField.text = reminderInstance.Name; 
        textField.autocorrectionType = UITextAutocorrectionTypeNo; 
        NSLog(@"Value = %@",textField.text); 
        [cell.contentView addSubview:textField]; 
        [self.fields addObject:textField]; 
       } 
      } 
     } 
      break; 

     case 1: 
     { 
      if (cell == nil) 
      { 
       cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifierF] autorelease]; 
       cell.backgroundColor = [[UIColor alloc]initWithPatternImage:[UIImage imageNamed:@"buttonbg-1.png"]]; 

       //Only add content to cell if it is new 
       if([cellIdentifierF isEqualToString: secondCellIdentifier]) 
       { 
        textField.tag = 102; 
        textField.text = reminderInstance.Event; 
        NSLog(@"Value = %@",textField.text); 
        [cell.contentView addSubview:textField]; 
        [self.fields addObject:textField]; 
       } 
      } 
     } 
      break; 

     case 2: 
     { 
      if (cell == nil) 
      { 
       cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifierF] autorelease]; 
       cell.backgroundColor = [[UIColor alloc]initWithPatternImage:[UIImage imageNamed:@"buttonbg-1.png"]]; 

       //Only add content to cell if it is new 
       if([cellIdentifierF isEqualToString: thirdCellIdentifier]) 
       { 
        textField.placeholder = @"Click here to set date and time"; 
        [self.textField setValue:[UIColor purpleColor] 
            forKeyPath:@"_placeholderLabel.textColor"]; 
        textField.inputView = self.datePicker; 
        textField.text = reminderInstance.Date; 
        textField.tag = 103; 
        NSLog(@"Value = %@",textField.text); 
        [cell.contentView addSubview:textField]; 
        [self.fields addObject:textField]; 
       } 
      } 
     } 
      break; 

     case 3: 
     { 
      if (cell == nil) 
      { 
       cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifierF] autorelease]; 
       cell.backgroundColor = [[UIColor alloc]initWithPatternImage:[UIImage imageNamed:@"buttonbg-1.png"]]; 

       //Only add content to cell if it is new 
       if([cellIdentifierF isEqualToString: fourthCellIdentifier]) 
       { 
        textField.tag = 105; 
        textField.text = reminderInstance.numDays; 
        textField.inputView = self.reminderPicker; 
        NSLog(@"Value = %@",textField.text); 
        [cell.contentView addSubview:textField]; 
        [self.fields addObject:textField]; 
       } 
      } 
     } 
      break; 

     case 4: 
     { 
      if (cell == nil) 
      { 
       cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifierF] autorelease]; 
       cell.backgroundColor = [[UIColor alloc]initWithPatternImage:[UIImage imageNamed:@"buttonbg-1.png"]]; 

       //Only add content to cell if it is new 
       if([cellIdentifierF isEqualToString: fifthCellIdentifier]) 
       { 
        checkboxButton = [[[UIButton alloc] initWithFrame:CGRectMake(16,1,120, 44)]autorelease]; 
        [checkboxButton setImage:[UIImage imageNamed:@"ewee.png"] forState:UIControlStateNormal]; 
        [checkboxButton addTarget:self action:@selector(toggleButton:) forControlEvents:UIControlEventTouchUpInside]; 

        NSString *one = reminderInstance.selString; 
        NSNumber* i = [NSNumber numberWithInt:[one intValue]]; 
        BOOL isOn = [i boolValue]; 

        if(isOn) 
        { 
         [checkboxButton setImage:[UIImage imageNamed:@"checkarrow.png"] forState:UIControlStateNormal]; 
        } 
        else 
        { 
         [checkboxButton setImage:[UIImage imageNamed:@"ewee.png"] forState:UIControlStateNormal]; 
        }    
        NSLog(@"String Val = %@",one); 

      [checkboxButton setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft]; 
      [checkboxButton setImageEdgeInsets:UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0)]; 
      [cell addSubview:checkboxButton]; 
      UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(55, 10, 225, 24)]; 
      label.text = @"Every Year"; 
      label.textColor = [UIColor whiteColor]; 
      label.backgroundColor = [UIColor clearColor]; 
      [cell addSubview:label]; 
      cell.textLabel.textColor = [UIColor whiteColor]; 
      [label release]; 
       } 
      } 

     } 
      break; 

     case 5: 
     { 
      if (cell == nil) 
      { 
       cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifierF] autorelease]; 
       cell.backgroundColor = [[UIColor alloc]initWithPatternImage:[UIImage imageNamed:@"buttonbg-1.png"]]; 

       //Only add content to cell if it is new 
       if([cellIdentifierF isEqualToString: sixthCellIdentifier]) 
       { 
        textField.placeholder = @"Enter the number here"; 
        [self.textField setValue:[UIColor purpleColor] 
            forKeyPath:@"_placeholderLabel.textColor"]; 
        textField.text = num; 
        textField.text = reminderInstance.number; 
        textField.tag = 106; 
        textField.userInteractionEnabled = YES; 
        textField.keyboardType = UIKeyboardTypeNumberPad; 
        NSLog(@"Value = %@",textField.text); 
        [cell.contentView addSubview:textField]; 
        [self.fields addObject:textField]; 
       } 
      } 
     } 
      break; 

     case 6: 
     { 
      if (cell == nil) 
      { 
       cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifierF] autorelease]; 
       cell.backgroundColor = [[UIColor alloc]initWithPatternImage:[UIImage imageNamed:@"reminderbuttonxl.png"]]; 

       //Only add content to cell if it is new 
       if([cellIdentifierF isEqualToString: seventhCellIdentifier]) 
       { 
        cell.backgroundColor = [UIColor clearColor]; 
        textView.clipsToBounds = YES; 
        textView = [[UITextView alloc]initWithFrame: CGRectMake(-2, -3, 307, 154)]; 
        UIImageView *imgView = [[[UIImageView alloc]initWithFrame: textView.frame]autorelease]; 
        imgView.image = [UIImage imageNamed: @"buttonbg_text.png"]; 
        [textView addSubview: imgView]; 
        [textView sendSubviewToBack: imgView]; 
        textView.backgroundColor = [UIColor clearColor]; 
        textView.delegate = self; 
        textView.tag = 11; 
        tagValues = textView.tag; 
        textView.textColor = [UIColor purpleColor]; 
        [cell.contentView addSubview:textView]; 
        textView.text = @"Your birthday wishes/other reminder body here"; 
        NSLog(@"Value = %@",textView.text); 
       } 
      } 
     } 
      break; 

     case 7: 
     { 
      if (cell == nil) 
      { 
       cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifierF] autorelease]; 
       cell.backgroundColor = [[UIColor alloc]initWithPatternImage:[UIImage imageNamed:@"buttonbg-1.png"]]; 

       //Only add content to cell if it is new 
       if([cellIdentifierF isEqualToString: eightCellIdentifier]) 
       { 
        textField.tag = 107; 
        textField.inputView = self.groupPicker; 
        tagValues = textField.tag; 
        textField.text = reminderInstance.remGroup; 
        NSLog(@"Value = %@",textField.text); 
        [cell.contentView addSubview:textField]; 
        [self.fields addObject:textField]; 
       } 
      } 
     } 
      break; 

     default: 
      break; 
    } 

    int size = [fields count]; 
    NSLog(@"there are %d objects in the array", size); 

    return cell; 
} 

ho fatto diversi tentativi per scoprire che cosa esattamente sta andando male anche ho controllato alcune domande here e there .Ma non ho trovato alcuna effic iente/appr. rispondere o che risolve il mio problema.

Quindi chiunque mi aiuti con suggerimenti preziosi o frammenti di codice di esempio.

Grazie a tutti in anticipo :)

+0

Non credo sia possibile caricare celle non visibili. La tabella estrarrà i dati dall'origine dati e caricherà solo le celle visibili.Le altre celle verranno caricate mentre scorri e diventeranno visibili. –

+0

dove stai facendo una nuova cella se non esiste – fibnochi

+0

@BillBurgess Grazie Mr.Burgess a mia conoscenza sapeva anche cosa hai detto .. ma sto affrontando un sacco di problemi a causa di questo perché senza apportare modifiche o toccare l'ultimo cella dopo lo scorrimento, non riesco ad aggiornare i dati anche senza farlo.Anche se l'utente entra nella vista tabella, popolato con i dati inseriti in quel punto del tempo. Quindi dire se l'utente modifica casualmente le prime 2 celle e fa clic . Quindi sta considerando l'ultimo campo (invisibile) i valori come zero anche se ci sono valori. –

risposta

4

Avrebbe senso che ci saranno un sacco di problemi provenienti dal modo in cui si sta costruendo la forma (che in realtà è il caso) quello che ho fatto io quando ho bisogno di costruire una tale forma è di usare costruire una vista normale con tutti i controlli per quanto tempo è lunga e avere quella forma in una vista di scorrimento e impostare la sua dimensione di contenuto con la dimensione della vista al suo interno. questo ti permetterebbe di avere un maggiore controllo su come vuoi che quel modulo guardi. e non penso di aver visto un'app utilizzando una vista tabella per una voce di modulo.

puoi utilizzare il generatore di interfacce per creare il tuo modulo (solo imbrogliare su Xcode e fare in modo che la vista principale e quella di scorrimento siano abbastanza grandi da poter vedere tutto sul builder, quindi ridimensionarla alla dimensione appropriata quando hai finito)

+0

Grazie mille Mr.Ehab Amer, ma non sono a conoscenza di come ottenere ciò che hai detto.puoi suggerirmi un tutorial o codice di esempio in cui posso prenderlo come riferimento e implementare lo stesso, grazie in anticipo :) –

+2

+1 per indicare la vera causa del problema. – lawicko

+0

potresti fornire maggiori informazioni sul modulo che stai cercando di costruire? Proverò e darò un passo alla volta. Puoi cercare "Interface Builder Tutorials" su google se non ti senti ancora a tuo agio con il generatore di interfacce. –

0

Quello che succede è che UITableView carica solo le celle visibili, e tutto il tempo in cui UITableView scorre, viene richiamata la callback cellForRowAtIndexPath:. Ma fammi capire bene Perché hai bisogno di un UITableView per creare un modulo? E come posso vedere, stai caricando una cella per sezione ... E stai solo inizializzando la cella. Cosa dovresti fare. Sottoclassi UITableViewCell e crea i tuoi oggetti lì.

quindi chiamare in questo modo:

cell = [[[MyCustomCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifierF] autorelease]; 

quindi è possibile chiamare esattamente il controller che si desidera. E devi controllare il comportamento di UITableView ogni volta che viene fatto scorrere. in questo modo:

case 7: 
     { 
      if (cell == nil) 
      { 
       cell = [[[MyCustomCellEigth alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifierF] autorelease]; 
       cell.backgroundColor = [[UIColor alloc]initWithPatternImage:[UIImage imageNamed:@"buttonbg-1.png"]]; 

       /*this should be done in the Custom Cell init method 
       if([cellIdentifierF isEqualToString: eightCellIdentifier]) 
       { 
        textField.tag = 107; 
        textField.inputView = self.groupPicker; 
        tagValues = textField.tag; 
        textField.text = reminderInstance.remGroup; 
        NSLog(@"Value = %@",textField.text); 
        [cell.contentView addSubview:textField]; 
        [self.fields addObject:textField]; 
       } 
       */ 
      } 
      else 
      { 
       //Control content 
       ((MyCustomCell*)cell).myTextField.text = @"SOME TEXT"; 
      } 
     } 
     break; 

Circa il selettore. Probabilmente funziona solo dopo aver fatto scorrere tutta la tabella, perché fa riferimento a un campo di testo che verrà aggiunto all'array solo dopo che la cella corrispondente sarà visibile.

Non c'è molto altro da fare. Ma segui questo e dovresti stare bene. Innanzitutto, sottoclasse UITableViewCell. Puoi creare i controlli da te in modo programmatico o con uno xib. Questo ti darà un maggiore controllo sulle cellule stesse. Informazioni sul selettore, invece di creare un array con controlli, crealo con i valori che dovrebbe avere. Una volta che qualcuno ha digitato qualcosa, salvalo usando UITextFieldDelegate. Spero che aiuti.

EDIT:

È necessario creare una sottoclasse della UITableViewCell. Su Xcode, crea un nuovo file. Seleziona Classe obiettivo-c. Nella schermata successiva, nella sottoclasse field di, selezionare UITableViewCell e denominare la cella di conseguenza. Questo creerà una classe che sovrascriverà il metodo initWithStyle:reuseIdentifier:. All'interno di questo metodo, dovresti inserire il tuo codice di init.

come questo:

#import <UIKit/UIKit.h> 

@interface MyCustomCellOne : UITableViewCell 
{ 
    UITextField *textField; 

} 
@end 

#import "MyCustomCellOne.h" 

@implementation MyCustomCellOne 

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 
{ 
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 
    if (self) { 
     // Initialization code 
        textField = [[UITextField alloc] initWithFrame:"YOUR FRAME"]; 
        textField.tag = 107; 
        textField.text = @"SOME TEXT"; 

        [self addSubview:textField];   
    } 
    return self; 
} 
+0

Grazie Raphael Ayres, ma non ho capito completamente "/ * questo dovrebbe essere fatto nel metodo di inizializzazione di Custom Cell" puoi modificare il mio post di conseguenza, grazie :) –

+0

Modificata la mia risposta per mostrare come si crea una cella personalizzata. –

+0

Oh k Mr.Raphael, grazie per tutte le preoccupazioni, ma solo un piccolo dubbio, dopo aver implementato lo stesso frammento di codice in EDIT parte della tua risposta, il resto della suddetta implementazione della mia rimane lo stesso eccetto i cambiamenti nel metodo init .. .destra? –

1

Sembra che si potrebbe essere meglio non usare la vista tavolo a tutti, ma con una vista di scorrimento, invece. Se hai veramente una quantità fissa di cose che stai per mostrare, puoi semplicemente metterle in una vista di scorrimento come viste (invece di celle di tabella) e il tuo codice diventerà molto più semplice.

Se ciò che si desidera dalla vista tabella è solo l'aspetto, è sufficiente utilizzare un'immagine di sfondo che sembra come si desidera e sovrapporre le visualizzazioni e i controlli su tale sfondo. Dovresti essere in grado di fare tutto questo in Interface Builder.

Se si segue questo approccio, il codice nel proprio controller di visualizzazione sarà ora quello che serve per gestire l'immissione di testo e la pressione dei pulsanti, e non è necessario preoccuparsi di una delegazione o di una sorgente dati vista tabella.

+0

Oh, l'ho già fatto usando la vista di scorrimento. Ma molti hanno suggerito che si tratta di un approccio di programmazione errato e ha detto "Usa vista tabella Invece ". Quindi ho cambiato il mio approccio di codifica da UIScrollView a UITableView. Come ho detto, implementerò lo stesso e tornerò da te, grazie mille –

+0

Ciao Mr.Mike non riesco a capire il motivo per cui y la mia vista di scorrimento non scorre. Ho implementato lo stesso cosa hai suggerito e anche implementato lo stesso codice in questo link: http: //www.roseindia.net/tutorial/iphone/tutorial/iphone/UIScrollView-Example-iPhone. html. Ma il problema è sorto, quando si cercavano domande riguardanti lo stesso ex: http: //stackoverflow.com/questions/3608949/iphone-uiscrollview-not-scrolling-when-adding-item-via-ib, cosa suggeriva era di imposta la dimensione del contenuto, anche allora non sono riuscito a ottenere lo scrolling. Per favore suggeriscimi cosa c'è che non va! –

1

Anche se questo sembra essere già stato risolto, quello che avrebbe potuto fare come un "trucco sporco" è quello di far scorrere l'intero tavolo fino al fondo prima di eseguire qualsiasi operazione. Qualcosa come [myTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES]; In questo modo sarebbe costretto a caricare tutto UITableCellView. Ricorda, questo non è il modo preferito, ma può funzionare nel caso sia richiesto un minimo cambiamento di codice.

Problemi correlati