0

基本上我正在制作一个列表视图,您可以将内容添加到顶部。我能想到的最好的方法是将 UITableViewCells 本身存储在一个 NSMutableArray 中——因为我可以简单地将它们从数组中拉出来,它们的所有数据都在对象中,而且这个列表视图永远不会超过 10 个单元格。

另请注意,我使用的是 Storyboard,因此使用了 initWithCoder。

以下代码是我正在尝试的,但它不起作用:

// This is where my NSMutableArray is initialized:

- (id)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super initWithCoder:aDecoder]) {
        if (!_CellsArray) {
            UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"TestCell"];
            _CellsArray = [NSMutableArray arrayWithObject:cell];
        }
    }
    return self;
}

//UITableView Delegate & DataSource Methods

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"TestCell"];
    [_CellsArray insertObject:cell atIndex:0];
    return [_CellsArray objectAtIndex:indexPath.row];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 10;
}

我意识到我可能以错误的方式处理这个问题,这就是我在这里的原因:)

谢谢你。

编辑:修复了代码中的一个类型(TimerCell -> UITableViewCell)

4

3 回答 3

3

让我们看看事物被调用的顺序以及发生了什么。

  1. 您的视图控制器未归档,因此initWithCoder:调用了您的方法。此方法创建一个可变数组并将一个实例TimerCell放入其中。所述实例未进一步配置(除非您已重写initWithStyle:reuseIdentifier:以进行某些配置)。

  2. 您的数据源方法tableView:numberOfRowsInSection:被调用,它告诉表视图有十行。

  3. 因此,你tableView:cellForRowAtIndexPath:被调用了十次。每次,它都会创建一个新实例UITableViewCell并将其插入到您的可变数组中。(十次调用后,您的可变数组TimerCell在索引 10 处包含一个,UITableViewCell在索引 0-9 处包含十个。)它不配置单元格的内容或外观,然后返回指定行索引处的单元格。在第一次调用时,系统会要求您输入第 0 行,因此将返回您刚刚创建并插入到索引 0 的单元格。在第二次调用中,系统要求您输入第 1 行,因此返回数组中索引 1 处的单元格 - 因为您刚刚在索引 0 处插入了一个新单元格,所以您在最后一次调用中创建的单元格已转移到索引 1 ,然后您再次返回它。每次调用都会继续:您返回相同的未配置UITableViewCell十次。


看起来您正试图超越 UIKit。这几乎从来都不是一件好事。(据说过早的优化是万恶之源。)

UITableView已经有小区重用机制;最好只跟踪您自己的单元格内容并让该机制发挥作用。我花了很长时间才输入这个,以至于其他答案已经写了描述如何做到这一点。查看他们,或查看 Apple 的文档或任何第三方UITableView教程。

于 2012-06-15T05:27:16.983 回答
0

为什么不将单元格信息存储在数组中。然后在-cellForRowAtIndexPath:方法中,只需提取更改每个单元格所需的数据。

这是一个简单的例子:


//Lets say you have an init like this that inits some cell information
- (id)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super initWithCoder:aDecoder]) {
        cellArray = [NSArray alloc] initWithObjects:@"firstCell",@"secondCell",@"thirdCell",nil];
    }
    return self;
}

//then for each cell, just extract the information using the indexPath and change the cell that way
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    // Configure the cell...
    cell.textLabel.text = [cellArray objectAtIndex:indexPath.row];

    return cell;
}

于 2012-06-15T05:22:01.167 回答
0

表视图不存储东西。相反,他们只是询问他们想要显示的数据,而您通常从其他地方(如 NSArray 或 NSFetchedResultsController)获取这些数据。只需将您想要的东西存储到某个数据容器中,然后让表格为您显示它们。

// Probably your data model is actually a member of your class, but for purposes of demonstration...
static NSArray* _myArray = [[NSArray alloc] initWithObjects:@"Bob", @"Sally", @"Joe", nil];

- (NSInteger) tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
    return [_myArray count];
}


- (UITableViewCell*) tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
    static NSString* CellIdentifier = @"TestCell";

    // Make a cell.
    UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if( cell == nil ) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

    // Setup the cell with the right content.       
    NSString* aString = [_myArray objectAtIndex:[indexPath row]];
    cell.textLabel = aString;

    return cell;
}

现在,如果您想要列表中的更多内容,请将其添加到您的数组中,然后您就完成了。

编辑:另一方面, initWithCoder: 通常不是为视图控制器进行初始化的最佳位置。原因是,在它被调用的时候,很有可能还没有加载东西(例如 IBOutlets)。我倾向于更喜欢 viewDidLoad(在这种情况下不要忘记在 viewDidUnload 中清理),或者 awakeFromNib。

于 2012-06-15T05:24:36.717 回答