我对iOS开发很陌生,我尝试了一些应该很容易的事情,我度过了一段糟糕的时光;每次用户单击现有行之一时,都会在TableView中添加额外的行。该操作没有真正的目的,我只是想了解 TableView 的行为。
所以我做了以下工作:
我使用了基于拆分视图的模板,并在 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的文档以及对以下问题的回答:在 iPhone 的表格视图中动态添加行和如何正确使用insertRowsAtIndexPaths?
第二个问题似乎解决了同样的问题,但我无法理解发生了什么。它们对数据源意味着什么?我更好地理解的回应如下:
这是一个两步过程: 首先更新数据源,以便 numberOfRowsInSection 和 cellForRowAtIndexPath 将为插入后数据返回正确的值。您必须在插入或删除行之前执行此操作,否则您将看到您收到的"无效行数"错误。
数据源的此更新意味着什么?
示例代码将不胜感激,因为我完全感到沮丧。
顺便说一句,我正在尝试的所有内容都与进入编辑模式无关,不是吗?
保持tableView:numberOfRowsInSection:
返回的计数同步!
因此,当您有 30 行然后告诉表视图插入新行时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];
等
答案很简单。如果要修改表视图,需要执行两个简单的步骤:
- 处理模型
- 处理表格动画
您已经执行了第二步。但是你错过了第一个。通常,当您处理表时,您会向其传递数据源。换句话说,要在其中显示一些数据。
一个简单的示例是使用包含虚拟数据的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];
}
看起来一个大问题是tableView:numberOfRowsInSection:
.您需要在该方法中返回正确的行数。
为此,通常最好为表视图维护NSArray
或NSMutableArray
项,以便在该函数中,您可以说:return [arrayOfValues count];
。将数组保留为视图控制器类的属性,以便在所有方法中都可以轻松访问它。
该数组也可用于cellForRowAtIndexPath:
。如果你有一个数组 NSString
,你可以说cell.text = [arrayOfValues objectAtRow:indexPath.row];
。
然后,当您想将项目添加到表视图中时,只需将其添加到数组并重新加载表即可,例如 [tableView reloadData];
.
尝试实现这个概念,让我知道它是怎么回事。
您也可以对dayanamic表单元格执行此操作
-(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;
}