3
votes

I've got a UITableView that I want to insert and delete rows in.

If I have an array of 10 values and start with the tableview including all rows, the table displays fine. Then if I want to filter out everything except [0, 1, 5]. I then go through the process of deleting rows at index paths: [2, 3, 4, 6, 7, 8, 9] and the returned number of rows is 3. I don't have to change my cell rendering code, it displays rows: [0, 1, 5].

However, if after having filtered everything, I want to come back to this table and load from persistence the table with rows [0, 1, 5], I'm having trouble. The table loads with number of rows: 3 and renders cells: [0, 1, 2].

I've tried initializing the table in viewDidLoad with 0 rows and then in viewDidAppear calling insertRows:[0, 1, 5] - but this throws an exception:

*** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-2380.17/UITableView.m:909

And I've verified that in viewDidLoad, the number of rows is printing 0, and just before this error is thrown, the number of rows printed is 3.

EDIT If I insert instead [0, 1, 2] - it works... but again... I ultimately need [0, 1, 5] showing up.

 - (void) viewDidAppear:(BOOL) animated
 {
    [super viewDidAppear:animated];

    NSArray *initializing_indeces = @[[NSIndexPath indexPathForRow:0 inSection:0], [NSIndexPath indexPathForRow:1 inSection:0], [NSIndexPath indexPathForRow:5 inSection:0]];
    [self.userDataTable insertRowsAtIndexPaths:initializing_indeces withRowAnimation:UITableViewRowAnimationAutomatic];
}
- (int) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Using different booleans, but the gist:
    if (viewDidLoad)
        return 0;
    if (viewDidAppear || filtered)
        return 3;
    if (expanded)
        return 10;
}
- (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CELL"];

    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CELL"];
    }


    [cell.textLabel setText:[NSString stringWithFormat:@"%i",indexPath.row]];

    return cell;
}
4
put relavent code here :)iPatel
In numberOfRowsInSection your should give 10 row .. And complite any oparation write [tableView reloadData];iPatel

4 Answers

1
votes

I have to keep track of the mapping myself:

- (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CELL"];

    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CELL"];
    }


    int row = indexPath.row;
    if (filtered) {
        // Translate 0 - 0
        // Translate 1 - 1
        // Translate 2 - 5
    }

    [cell.textLabel setText:[NSString stringWithFormat:@"%i", row]];

    return cell;
}

I ended up using an NSMutableArray that, when filtered, becomes [0, 1, 5] so accessing the index of that array, indexPath.row of 2 returns 5.

1
votes

@Fish stix

[cell.textLabel setText:[NSString stringWithFormat:@"%i",indexPath.row]];

this method in your code clearly states that, text will be NSString with indexPath.row's value. Now when you are deleting your rows and data source, from 10 = [0, 1, 5] + [2, 3, 4, 6, 7, 8, 9] to 3 = [0, 1, 5]. Your data source has been reduced to an array of count 3. Hence you will get three rows only as returned bby numberOfRowsInSection method. The three rows will have these indexPath.row's 0, 1, 2. And hence you are getting 0,1 ,2 instead of 0, 1 ,5.

if you print the indexPath, in cellForRowAtIndexPath method (after filtering) you will see them as [0, 0] [0, 1] [0, 2] meaning section 0, and row number 0, 1, 2 respectively. And hence your result

As in to get your desired result. do this. take a property @property (retain, nonAtomic) NSArray *dataArray;

in viewDidLoad: self.dataArray = [NSArray arrayWithObjects:@"0",@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9", nil];

in numberOfRowsInSection return [array count];

and in cellForRow [cell.textLabel setText:[self.dataArray objectAtIndex:indexPath.row]];

Now just change the dataSource (i mean dataArray) to filtered or expanded state) in viewWillAppear or wherever you want and reload the table data using [self.tableView reloadData];

Hope I am clear. Cheers, have fun.

0
votes

First in your case numberOfRowsInSection return NSInteger not int, so please change it

I don't Exactly what is The resone. I assume That Problem must be connected to this part in your code,

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

Generally you are making a mistake in one of these data source methods. May be it's impossible to say what exactly is wrong but it could be something like: You are telling the table view in thenumberOfRowsInSection (in your case 10 )and in thecellForRowAtIndexPath you then only handle 10 - 1 rows for example. If you show us your implementation of your data source it would be much easier to tell what's going on.

0
votes

For each time inserting you need to reload the tableview using [tableView realodData]