8 votes

Charger toutes les cellules de UITableView avant de les faire défiler.

J'ai une UITableView avec 8 cellules (sections) au total, dont 6 contiennent des textFields en tant que sous-vues et 2 contiennent un bouton et l'autre une vue de texte.Maintenant, j'ai un problème ici, car nous sommes tous conscients que lorsque la vue apparaît, seules les cellules visibles se chargent.Donc, lorsque mon application est chargée, je suis en mesure de voir 5 cellules, les 4 premières contenant des champs de texte et la 5e cellule avec le bouton.Je peux voir le tableau compte est de 4 lorsque je l'ai affiché par le biais de la journalisation dans la console, c'est à dire.

there are 4 objects in the array

Maintenant, après avoir fait défiler la vue du tableau, je peux observer ce qui suit :

there are 6 objects in the array

Donc, ce qui se passe, c'est que si je veux sauvegarder les données saisies dans la vue tableau, ou si je veux modifier les données existantes, je suis obligé de faire défiler la vue tableau et de saisir les valeurs dans la dernière cellule également. Donc, cela ne peut pas toujours être le cas avec l'utilisateur parce que nous ne pouvons pas nous attendre à ce qu'il/elle fasse défiler la vue tableau et saisisse les entrées complètes du formulaire/de la vue tableau.

De plus, j'ai une vue de sélecteur comme vue d'entrée pour la dernière cellule contenant le champ de texte comme sous-vue. Par conséquent, dans ma vue de sélecteur a fait la méthode de sélection de ligne, je suis confronté à un problème de crash avec la dernière cellule / section (textField comme sous-vue) contenant une vue de sélecteur ici est mon extrait de code pour la méthode :

-(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...

Je me demande pourquoi, parfois, après avoir sélectionné des valeurs dans la vue du sélecteur (dernière cellule de la section), le système se bloque et parfois il fonctionne bien. cas 107 Un certain nombre de fils de temps comme indiqué dans l'image ci-dessous :

enter image description here

Y a-t-il un moyen de charger toutes les cellules en même temps pour que tous les champs de texte soient ajoutés au tableau avant le défilement ?

CODE EDITIONNEL plus détaillé pour la compréhension :

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

J'ai fait plusieurs tentatives pour trouver ce qui ne va pas exactement et j'ai également vérifié certaines questions. aquí y Mais je n'ai pas pu trouver de réponse efficace/appr. ou qui résout mon problème.

N'hésitez pas à m'aider en me proposant des suggestions ou des exemples de code.

Merci d'avance à tous :)

5voto

Ehab Amer Points 382

Il serait logique que de nombreux problèmes proviennent de la façon dont vous construisez le formulaire (ce qui est en fait le cas). ce que j'ai fait moi-même quand j'ai eu besoin de construire un tel formulaire, c'est de construire une vue normale avec tous les contrôles, quelle qu'en soit la longueur, et d'avoir ce formulaire dans une vue défilante et de définir la taille de son contenu avec la taille de la vue qu'il contient. cela vous permettrait d'avoir plus de contrôle sur la façon dont vous voulez que le formulaire se présente. et je ne pense pas avoir vu une application utilisant une vue de table pour une entrée de formulaire.

vous pouvez utiliser le constructeur d'interface pour construire votre formulaire (il suffit de tricher sur Xcode et de rendre la vue principale et la veine de défilement suffisamment grandes pour que vous puissiez tout voir sur le constructeur, puis de le redimensionner à la taille appropriée lorsque vous avez terminé)

1voto

VijayKumar Points 236

Bien que ce problème semble déjà résolu, ce qui aurait pu être fait comme un "dirty hack" est de faire défiler la table entière jusqu'en bas avant d'effectuer toute opération. Quelque chose comme [myTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES]; De cette façon, il serait obligé de charger toutes les UITableCellView. Rappelez-vous, ce n'est pas la méthode préférée, mais elle peut fonctionner si un changement minimal du code est nécessaire.

1voto

Mike Hay Points 1728

Il semble que vous feriez mieux de ne pas utiliser de vue tableau du tout, mais d'utiliser une vue défilante à la place. Si vous avez vraiment un nombre fixe d'éléments à afficher, vous pouvez les disposer dans une vue défilante sous forme de vues (au lieu de cellules de tableau) et votre code sera beaucoup plus simple.

Si ce que vous attendez de la vue de la table est seulement l'apparence, vous pouvez simplement utiliser une image d'arrière-plan qui ressemble à ce que vous voulez, et superposer les vues et les contrôles sur cet arrière-plan. Vous devriez être en mesure de faire tout cela dans Interface Builder.

Si vous adoptez cette approche, le code de votre contrôleur de vue sera juste ce dont vous avez besoin pour gérer la saisie de texte et les pressions sur les boutons, et vous n'aurez pas à vous soucier d'un délégué de vue de table ou d'une source de données.

0voto

Raphael Ayres Points 477

Ce qui se passe, c'est que l'UITableView ne charge que les cellules visibles, et à chaque fois que l'UITableView défile, le callback cellForRowAtIndexPath: est appelé. Mais laissez-moi résumer. Pourquoi avez-vous besoin d'un UITableView pour créer un formulaire ? Et comme je peux le voir, vous chargez une cellule par section... Et, vous ne faites qu'initialiser la cellule. Ce que tu devrais faire. Sous-classez UITableViewCell et créez vos objets là.

puis appelez comme ceci :

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

Vous pouvez alors appeler exactement le contrôleur que vous voulez. Et vous devez contrôler le comportement de votre UITableView lorsqu'il est défilé. comme ceci :

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;

A propos du sélecteur. Il ne fonctionne probablement qu'une fois que vous avez fait défiler tout le tableau, car il fait référence à un textField qui ne sera ajouté au tableau que lorsque la cellule correspondante sera visible.

Il n'y a plus grand-chose à faire. Mais suivez ces instructions et tout devrait bien se passer. Premièrement, sous-classez UITableViewCell. Vous pouvez créer les contrôles vous-même de manière programmatique ou avec un xib. Cela vous donnera plus de contrôle sur les cellules elles-mêmes. À propos du sélecteur, au lieu de créer un tableau avec des contrôles, créez-le avec les valeurs qu'il devrait avoir. Une fois que quelqu'un a tapé quelque chose, enregistrez-le en utilisant le UITextFieldDelegate. J'espère que cela vous aidera.

EDITAR:

Vous devez créer une sous-classe de l'UITableViewCell. Sur Xcode, créez un nouveau fichier. Sélectionnez objective-c Class. Sur l'écran suivant, dans le champ subclass of, sélectionnez UITableViewCell et nommez votre cellule en conséquence. Ceci créera une classe qui remplacera la classe initWithStyle:reuseIdentifier: méthode. A l'intérieur de cette méthode, vous devez mettre votre code init.

comme ça :

#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;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X