在tableview单元格中的UIView无法正常工作

时间:2014-05-16 04:18:39

标签: ios uitableview

我有一个tableview,它接收一个由字典组成的数组。每个字典都有一个AVAsset和音频数据。我在每个自定义tableview单元格中都有一个UIView,它显示AVAsset的波形,并在选择特定单元格时播放音频数据。每次使用addObject向数组添加字典时,tableview都能正常工作。但是,我希望最新的字典位于tableView的顶部,所以我使用insertObject:AtIndex:0,但由于某种原因,添加到数组的第一个字典的UIView保持在顶部单元格,其他UIViews根本不加载。但是,每个音频数据都在正确的单元格中。因此,如果我在数组中有三个字典,则只有第一个字典的UIView显示在顶部单元格中,其下方有两个空单元格。奇怪的部分是每个字典的音频数据与正确的单元格相关联。超级混乱,但我很确定这与tableview单元格的UIView如何在重新加载tableview时响应有关。随机地,我可以得到第二个UIView,但它不一致。对不起,如果这让你头疼!

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

    static NSString* word = @"audioTableCell";

    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"audioTableCell" owner:self options:nil];
    OSAudioTableCell *cell =[self.audioTable dequeueReusableCellWithIdentifier:word];
    if(!cell)
    {
        cell= (OSAudioTableCell*)[nib objectAtIndex:0];


        cell.selectionStyle = UITableViewCellSelectionStyleNone;

        //Dictionary from the array
        NSDictionary * packageInArray = [self.audioTableArray objectAtIndex:indexPath.row];

        //Not related to UIView
        cell.userName.text = [packageInArray objectForKey:@"userName"];
        cell.profilePicture.image = [UIImage imageWithData:[packageInArray objectForKey:@"profileImageData"]];


        //This is for the UIView
        [cell setProgress:0];
        [cell setAsset:[packageInArray objectForKey:@"asset"]];
        [cell setBackgroundColor:[UIColor clearColor]];
        [cell.waveView setBackgroundColor:[UIColor clearColor]];

        //Not related to UIView
        CALayer *imageLayer = cell.profilePicture.layer;
        [imageLayer setCornerRadius:20];
        imageLayer.borderColor = (__bridge CGColorRef)([UIColor grayColor]);
        [imageLayer setMasksToBounds:YES];
    }


    return cell;
}

- (void)viewDidLoad
{

    [super viewDidLoad];

    [arrayStatusLabel setHidden:YES];

    self.primaryUser = [OSPrimaryUser getUserInstance];
    self.primaryUser.userAudioArray = [self.primaryUser createAudioArray];

    self.audioTableArray = self.primaryUser.userAudioArray;

    [self.audioTable registerNib:[UINib nibWithNibName:@"audioTableCell" bundle:nil] forCellReuseIdentifier:@"audioTableCell"];


    if([self.audioTableArray count] == 0)
    {
        [self.audioTable setHidden:YES];
         [arrayStatusLabel setHidden:NO];
    }
    else
    {
        [self.audioTable setHidden:NO];
        [arrayStatusLabel setHidden:YES];

    }

    [self.navigationItem setHidesBackButton:YES];

    [self.audioTable setSeparatorInset:UIEdgeInsetsZero];

    [self.audioTable reloadData];
}

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

    [self.audioTable reloadData];

    if([self.audioTableArray count] == 0)
    {
        [self.audioTable setHidden:YES];
        [arrayStatusLabel setHidden:NO];
    }
    else
    {
        [self.audioTable setHidden:NO];
        [arrayStatusLabel setHidden:YES];

    }
}

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

    [self.audioTable reloadData];
}

2 个答案:

答案 0 :(得分:0)

我认为问题在于您将所有数据添加到if(!cell)子句中的单元格中。最佳做法是在viewDidLoad中注册您的nib(使用registerNib:forIdentifier :)而不是手动加载nib。您将保证以这种方式获取单元格,并且您可以一起消除if(!cell)子句。关于CALayer的最后一段代码并不需要在每次调用cellForRowAtIndexPath:方法时运行,因此我将该代码移动到单元的init方法。

编辑后:

-(void)viwDidLoad {
    [super viewDidLoad];
    [self.tableView registerNib:[UINib nibWithNibName:@"OSAudioTableCell" bundle:nil] forCellReuseIdentifier:@"audioTableCell"];
}



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

    static NSString* word = @"audioTableCell";
    OSAudioTableCell *cell =[self.audioTable dequeueReusableCellWithIdentifier:word];
   // configure your cell
   return cell;

}

只要您在cellForRowAtIndexPath中使用相同的标识符" audioTableCell",就可以保证获得有效的单元格。

答案 1 :(得分:0)

在我看来,当你从dequeueReusableCellWithIdentifier接收一个对象时,你只是重新使用那个单元格而不更新其中的值。

也就是说,你有:

OSAudioTableCell *cell =[self.audioTable dequeueReusableCellWithIdentifier:word];
if (!cell)
{
    // create a cell ...snip

    // set all the cell content ...snip
}

// You probably want to set the cell content...
// ...out here, instead.

return cell;

在你的问题中写的方式(我假设你从你的项目中复制/粘贴),每个重复使用的单元格将只显示它之前的任何信息。

在编辑中添加:了解一下,当您创建一个包含100行的表时,iOS确实= = =分配100个单元格,每行一个。相反,它只为屏幕上的内容分配足够的单元格 - 可能是7或8,具体取决于表格和行的高度 - 然后,当一个单元格滚出屏幕时,它会被放入队列中下次调用dequeueReusableCellWithIdentifier时重用:

因此,第二次获取单元格时,视图已包含您上一次初始化的所有子视图。

rdelmar的答案显示了如何正确创建基于nib的单元格。重要的是:在之后填充单元格的内容您有一个有效的单元格,而不是仅在您创建它时,这是您的代码片段显示的内容。请记住:第17行的单元格可能是用于第3行的回收单元格。

所有单元格内容视图 - 显示波形,进度条,图像或单元格中的任何其他内容的视图 - 需要在<<>之后设置的值和/或内容 / strong>您确认自己有一个有效的单元格, 后验证您是否拥有有效的观看次数。

对于非基于nib的单元格,它通常看起来像这样(在浏览器中键入;可能需要调整):

OSAudioTableCell *cell =[self.audioTable dequeueReusableCellWithIdentifier:word];
if (cell == nil)
{
    // create a cell
    [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: CellIdentifier];
}

UILabel *cellLabel = [cell viewWithTag: kMyLabelTag];
if (myLabel == nil)
{
    cellLabel = [UILabel new];
    cellLabel = kMyLabelTag;
    // set-up frame, whatever else...
    [cell addSubView: cellLabel];
}
cellLabel = someGoodText;  // NOTE: we do this whether the field is new or old!

SpecialView *cellView = [cell viewWithTag: kMyViewTag];
if (cellView == nil)
{
    cellView = [SpecialView new];
    cellView = kMyViewTag;
    // set-up frame, whatever else...
    [cell addSubView: cellView];
}
cellView.specialField = someValue;  // NOTE: we do this whether the field is new or old!

// etc., repeat for other cell-content.

return cell;

对于基于nib的单元格,从笔尖加载各种子视图,因此您可以假设它们存在并跳过if (cellSubView == nil) createCelLSubview部分。

希望有所帮助!