Загрузите все ячейки в UITableView перед прокруткой - PullRequest
8 голосов
/ 23 февраля 2012

У меня есть UITableView с 8 ячейками (разделами), в которых 6 из них содержат текстовые поля в качестве подпредставлений, а 2 из них содержат кнопку, а другую - текстовое представление. Теперь у меня возникла проблема, так как мы все Помните, что когда появляется только представление, загружаются видимые ячейки. Итак, когда мое приложение загружается, я могу просмотреть 5 ячеек, первые 4, содержащие текстовые поля, и 5-ю ячейку с кнопкой. Я вижу, что количество массивов равно 4 когда я отобразил это через вход в систему консоли, то есть

there are 4 objects in the array

Теперь, прокрутив представление таблицы, я могу наблюдать следующее:

there are 6 objects in the array

Итак, что происходит, если я хочу сохранить данные, введенные в табличное представление, или сказать «редактировать», чтобы внести изменения в существующие данные, я вынужден прокрутить табличное представление и также ввести значения в последнюю ячейку. не всегда может быть с пользователем, потому что мы не можем ожидать, что он / она прокрутит представление таблицы и введет полные записи в ячейке формы / представления таблицы. Что бы он ни сделал, он / она внесет изменения и просто нажмет кнопку «Готово» / «Сохранить все, что когда-либо». это ..!

Более того, в качестве представления ввода для последней ячейки, содержащей текстовое поле в качестве подпредставления, используется представление выбора. Поэтому в моем представлении выбора выбран метод строки. Я столкнулся с проблемой сбоя последней ячейки / раздела (textField как подпредставление), содержащего средство выбора. посмотреть вот мой фрагмент кода для метода:

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

Интересно, почему несколько раз после выбора значений в представлении выбора (ячейка последнего раздела) иногда происходит сбой, а иногда работает нормально. Иногда происходит сбой на указанной выше строке, прокомментированной в случае 107 , иногда основной пул автоматического выпуска. Некоторое время потока, как показано на снимке ниже:

enter image description here

Так есть ли способ загрузить все ячейки одновременно, чтобы все текстовые поля были добавлены в массив перед прокруткой. Не может быть никаких проблем, я считаю

Более подробный отредактированный код для понимания:

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

Я сделал несколько попыток выяснить, что именно идет не так, также я проверил некоторые вопросы здесь и там . Но не удалось найти какой-либо эффективный / ок. ответ или это решит мою проблему.

Так что, пожалуйста, помогите мне с ценными предложениями или примерами фрагментов кода.

Заранее всем спасибо :)

Ответы [ 4 ]

4 голосов
/ 23 февраля 2012

Имеет смысл, что будет много проблем, связанных с тем, как вы строите форму (что на самом деле так) То, что я делал сам, когда мне нужно было создать такую ​​форму, это использовать сборку обычного представления со всеми элементами управления, какими бы длинными они ни были, и иметь эту форму в виде прокрутки и установить размер ее содержимого в соответствии с размером представления в этом. это позволит вам лучше контролировать, как вы хотите, чтобы эта форма выглядела. и я не думаю, что видел приложение, использующее представление таблицы для ввода формы.

вы можете использовать конструктор интерфейса для создания вашей формы (просто чит в Xcode и сделайте основной вид и прокрутку достаточно большими, чтобы вы могли видеть все на компоновщике, а затем измените его размер до нужного размера, когда вы закончите)

1 голос
/ 15 марта 2012

Хотя это, кажется, уже решено, то, что можно было бы сделать как «грязный хак», - это заставить всю таблицу прокручиваться до дна перед выполнением какой-либо операции. Что-то вроде [myTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES]; Таким образом, он будет вынужден загрузить все UITableCellView. Помните, это не предпочтительный способ, но может работать, если требуется минимальное изменение кода.

1 голос
/ 23 февраля 2012

Похоже, что вам лучше не использовать табличное представление вообще, а вместо этого использовать представление с прокруткой.Если у вас действительно есть фиксированное количество вещей, которые вы собираетесь отображать, вы можете просто разместить их в виде прокрутки как представления (вместо ячеек таблицы), и ваш код станет намного проще.

Если то, что вы хотите из табличного представления, это просто внешний вид, вы можете просто использовать фоновое изображение, которое выглядит так, как вы хотите, и наложить представления и элементы управления на этот фон.Вы должны быть в состоянии сделать все это в Интерфейсном Разработчике.

Если вы выберете этот подход, код в вашем контроллере представления теперь будет именно тем, что вам нужно для обработки ввода текста и нажатия кнопок, и вам не нужно беспокоиться о делегате табличного представления или источнике данных..

0 голосов
/ 23 февраля 2012

В результате UITableView загружает только видимые ячейки, и все время прокрутки UITableView вызывается обратный вызов cellForRowAtIndexPath:. Но позвольте мне понять это прямо. Зачем вам нужен UITableView для создания формы? И, как я вижу, вы загружаете одну ячейку на раздел ... И вы только инициализируете ячейку. Что ты должен делать. Подкласс UITableViewCell и создавать свои объекты там.

тогда звоните так:

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

Тогда вы можете вызвать именно тот контроллер, который вам нужен. И вы должны контролировать поведение вашего UITableView всякий раз, когда он прокручивается. как это:

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;

О сборщике. Вероятно, он работает только после прокрутки всей таблицы, поскольку он ссылается на textField, который будет добавлен в массив только после того, как соответствующая ячейка станет видимой.

Больше нечего делать. Но следуйте этому, и у вас все будет хорошо. Во-первых, подкласс UITableViewCell. Вы можете создавать элементы управления самостоятельно программно или с помощью xib. Это даст вам больше контроля над самими клетками. О средстве выбора, вместо создания массива с элементами управления, создайте его со значениями, которые он должен иметь. После того, как кто-то что-то напечатал, сохраните его с помощью UITextFieldDelegate. Надеюсь, это поможет.

EDIT:

Вы должны создать подкласс UITableViewCell. На Xcode создайте новый файл. Выберите цель-C Class. На следующем экране в подклассе поля выберите UITableViewCell и присвойте имя соответствующей ячейке. Это создаст класс, который переопределит метод initWithStyle:reuseIdentifier:. Внутри этого метода вы должны поместить свой код инициализации.

как это:

#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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...