Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load all cells in UITableView before scrolling

I have a UITableView with 8 cells(sections) in total in which 6 of them contain textFields as subviews and out of 2 one containing button and the other containing text view.Now I have got a problem here,as we are all aware that when ever the view appears only,the visible cells loads.So when my app gets loaded,I am able to view 5 cells,the first 4 containing text fields and the 5th cell with button.I can see the array count is 4 when i displayed it through logging in console i.e.

there are 4 objects in the array

Now after scrolling the table view,I can observe the following:

there are 6 objects in the array

So,what's happening is If I am to save the data entered in the table view,or say edit to make changes to existing data,I am forced to scroll the table view and enter the values in last cell too.So that cannot be the case always with the user because we can't expect him/her to scroll the table view and enter the complete form/table view cell entries.What ever changes he/she makes they will and just click done/save what ever it is..!

More over I am having a picker view as input view for last cell containing text field as subview.Hence in my picker view did select row method I am facing crash problem with last cell/section(textField as subview) containing a picker view here is my code snippet for the method:

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

I wonder why some times after selecting values from picker view(last section cell) crashes some times and some times works fine.Some times it crashes at the above line commented in case 107,some times in main autorelease pool.Some time thread as shown in snap below:

enter image description here

So is there any way that we can load all cells at once so that all the text fields get added to array before scrolling.There cannot be any problem I believe

More Detailed EDITED CODE for understanding:

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

I have made several attempts to find out what exactly is going wrong also I checked some questions here and there.But couldn't find any efficient/appr. answer or that solves my issue.

So anyone please help me with valuable suggestions or sample code snippets.

Thanks all in advance :)

like image 910
Eshwar Chaitanya Avatar asked Feb 23 '12 14:02

Eshwar Chaitanya


3 Answers

It would make sense that there will be a lot of issues coming from the way you are building the form (which is actually the case) what I've been doing myself when I need to build a such a form is to use build a normal view with all the controls whatever long it is and have that form in a scroll view and set its content size with the size of the view in it. that would let you have more control on how you want that form to look. and I don't think I've seen an app using a tableview for a form entry.

you can use interface builder to build your form (just cheat on Xcode and make the main view and the scroll vew large enough so u can see everything on the builder, then resize it to the appropriate size when you are done)

like image 167
Ehab Amer Avatar answered Nov 17 '22 04:11

Ehab Amer


It sounds like you might be better off not using a table view at all, but using a scroll view instead. If you really do have a fixed amount of things that you are going to display, you can just lay these out on a scroll view as views (instead of table cells) and your code will get a lot simpler.

If what you want out of the table view is just the appearance, you can simply use a background image that looks the way you want, and overlay the views and controls over that background. You should be able to do all of this in Interface Builder.

If you take this approach, the code in your view controller will now be just what you need to handle the text input and button presses, and you don't need to worry about a table view delegate or data source.

like image 21
Mike Hay Avatar answered Nov 17 '22 05:11

Mike Hay


Although this seems to be already solved, what could have done as a "dirty hack" is to make the entire table scroll till bottom before performing any operation. Something like [myTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES]; This way it would be forced to load all the UITableCellView. Remember, this is not preferred way, but can work in case minimum code change is required.

like image 1
VijayKumar Avatar answered Nov 17 '22 03:11

VijayKumar