如何将我的UITableViewCells存储在NSMutableArray中?

时间:2012-06-15 04:52:36

标签: iphone ios uitableview

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

另请注意,我正在使用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)

3 个答案:

答案 0 :(得分:3)

让我们看一下调用的顺序和发生的事情。

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

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

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


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

    UITableView已经有了一种细胞重用机制;最好只跟踪你自己的单元内容并让这个机制做它的事情。我花了这么长时间才输入这个,其他的答案已经写成描述如何做到这一点。查看它们,或Apple的文档或任何第三方UITableView教程。

答案 1 :(得分: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;
}

答案 2 :(得分: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。