在TableView iOS中添加一行

时间:2012-05-31 17:08:21

标签: ios tableview

我对iOS开发很陌生,我在尝试一些应该很容易的事情时度过了一段可怕的时光;每次用户单击其中一个现有行时,在TableView中添加一行。这个动作没有真正的目的,我只是想了解TableView的行为。

所以我做了以下事情:

我使用了基于Split View的模板,并在RootViewController中将行数更改为30.

- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section {
   // Return the number of rows in the section.
   return 30;
}

方法tableView:didSelectRowAtIndexPath以下列方式查找:

- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    /*
    When a row is selected, set the detail view controller's detail item to the item associated with the selected row.
    */
   NSMutableArray* paths = [[NSMutableArray alloc] init];
   NSIndexPath *indice = [NSIndexPath indexPathForRow:30 inSection:0];
   [paths addObject:indice];
   detailViewController.detailItem = [NSString stringWithFormat:@"Second Story Element %d with all its information and bla bla bla", indexPath.row];
   [[self tableView] beginUpdates];
   [self.tableView insertRowsAtIndexPaths:(NSArray *) paths withRowAnimation:UITableViewRowAnimationNone];
   [[self tableView] endUpdates];
}

当我执行程序并单击其中一个元素时,我收到以下错误:

  
    

***由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'无效更新:第0节中的行数无效。更新后的现有部分中包含的行数(30)必须等于更新前该部分中包含的行数(30),加上或减去从该部分插入或删除的行数(插入1个,删除0个)。'

  

我没有更改模板提供的代码的任何其他部分。

我非常详细地阅读了Apple的文档以及对以下问题的回答: Add a row dynamically in TableView of iphonehow to properly use insertRowsAtIndexPaths?

第二个问题似乎解决了同样的问题,但我无法理解正在发生的事情。他们对dataSource有什么意义?我理解的反应更好地说明如下:

  
    

这是一个两步过程:     首先更新数据源,以便numberOfRowsInSection和cellForRowAtIndexPath将返回插入后数据的正确值。您必须在插入或删除行之前执行此操作,否则您将看到“无效行数”错误。

  

此数据源更新意味着什么?

示例代码将非常感激,因为我完全感到沮丧。

顺便说一下,我尝试的一切与进入编辑模式无关,有吗?

4 个答案:

答案 0 :(得分:14)

您需要保持tableView:numberOfRowsInSection:返回的计数同步!

因此,当您有30行然后告诉tableview插入新行时,您需要确保tableView:numberOfRowsInSection:现在返回31行。

- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section
{
   return self.rowCount;
}

- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
   self.rowCount++;

   [self.tableView beginUpdates];
   [self.tableView insertRowsAtIndexPaths:(NSArray *) paths withRowAnimation:UITableViewRowAnimationNone];
   [self.tableView endUpdates];
}

在实践中,您可能会使用数组来跟踪行return [self.rows count];

答案 1 :(得分:3)

答案很简单。如果要修改表视图,则需要执行两个简单步骤:

  1. 处理模型
  2. 处理表动画
  3. 您已经执行了第二步。但你错过了第一个。通常当你处理一个表时,你传递一个数据源。换句话说,一些数据要显示在其中。

    一个简单的例子是使用包含虚拟数据的NSMutableArray(顾名思义它是动态的)。

    例如,在.h

    中创建如下所示的属性
    @property (nonatomic, strong) NSMutableArray* myDataSource;
    

    并在.m中将其合成为:

    @synthesize myDataSource;
    

    现在,您可以alloc-init该数组并将其填充为以下内容(例如,在控制器的viewDidLoad方法中)。

    self.myDataSource = [[NSMutableArray alloc] init];
    [self.myDataSource addObject:@"First"];
    [self.myDataSource addObject:@"Second"];
    

    然后,您可以执行以下操作,而不是硬编码您将显示的行数(在您的情况下为30),您可以执行以下操作:

    - (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section    {
    
       return [self.myDataSource count];
    }
    

    现在,在您didSelectRowAtIndexPath委托中,您可以添加第三个元素。

    - (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    
       [self.myDataSource addObject:@"Third"];
    
       [[self tableView] beginUpdates];
       [self.tableView insertRowsAtIndexPaths:(NSArray *) paths withRowAnimation:UITableViewRowAnimationNone];
       [[self tableView] endUpdates];
    }
    

答案 2 :(得分:2)

tableView:numberOfRowsInSection:看起来像一个大问题。您需要在该方法中返回正确的行数。

要做到这一点,通常最好为表格视图维护NSArrayNSMutableArray项,因此在该函数中,您可以说:return [arrayOfValues count];。将数组保留为视图控制器类的属性,以便在所有方法中都可以轻松访问它。

该阵列也可用于cellForRowAtIndexPath:。如果您有一个NSString数组,则可以说cell.text = [arrayOfValues objectAtRow:indexPath.row];

然后,当您想要将项目添加到表格视图时,您只需将其添加到数组并重新加载表格,例如[tableView reloadData];

尝试实施这个概念,让我知道它是怎么回事。

答案 3 :(得分:0)

您也可以为动态表格单元格

执行此操作
    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
        {
            return [arrayStationStore count];
        }
        -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
        {
            static NSString *cellIndentyfire;
            UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIndentyfire];
            if (cell ==  nil)
            {
                cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIndentyfire];


            }



            cell.textLabel.text = [arrayStationStore objectAtIndex:indexPath.row];
            return cell;
        }

-(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Check if current row is selected
    BOOL isSelected = NO;
    if([tblStationName cellForRowAtIndexPath:indexPath].accessoryType == UITableViewCellAccessoryCheckmark)
    {
        isSelected = YES;
    }

    if(isSelected)
    {
        [tblStationName cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryNone;
        [arrayReplace removeObject:indexPath];
        NSLog(@"array replace remove is %@ ",arrayReplace);
    }
    else
    {
        [tblStationName cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark;
        [arrayReplace addObject:indexPath];
         NSLog(@"array replace add is %@ ",arrayReplace);
    }
    return indexPath;
}