【问题标题】:Continuously update UISlider within UITableViewCell在 UITableViewCell 内不断更新 UISlider
【发布时间】:2012-08-31 13:58:52
【问题描述】:

我希望将 UISlider 用作“Audio VU Meter”类型指示器,其中音轨的电平会不断更新 UISlider 的值。我的应用程序中的每个轨道当前都位于一个 UITableViewCell 中,VU Meter 是单元格内容视图中的一个子视图。一次显示多达 12 首曲目。

VU 表的更新是通过 TCP/IP 端口进行的,所以一旦我收到新的 VU 电平并设置推子值 (mySlider.value = newValue)。但是,让滑块立即更新的唯一方法是调用performSelectorOnMainThread:@selector(reloadData) withObject:myTableView waitUntilDone:NO。似乎我不应该重新加载整个表的数据。

代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    TrackTableCell *cell = (TrackTableCell *)[tableView dequeueReusableCellWithIdentifier:@"TrackTableCell"];

    if(cell == nil)
    {
        [[NSBundle mainBundle] loadNibNamed:@"TrackTableCell" owner:self options:nil];
        cell = [self trackTableCell];

        /**************************/
        /********* FADER  *********/
        /**************************/
        VolumeSlider *fader = [[VolumeSlider alloc] initWithFrame:CGRectMake(0, 0, 265, 30)];
        [fader setRotatedThumbImage:[UIImage imageNamed:@"FaderCap.png"]];
        [fader setRotatedMinTrackImage:[UIImage imageNamed:@"VolumeSlider.png"]];
        [fader setRotatedMaxTrackImage:[UIImage imageNamed:@"VolumeSlider.png"]];

        [fader addTarget:self action:@selector(volumeFaderSliderAction:) forControlEvents:UIControlEventValueChanged];

        fader.value = 0;

        // rotate the slider
        fader.transform = CGAffineTransformMakeRotation(-M_PI_2);
        [cell.contentView addSubview:fader];

        fader.bounds = CGRectMake(0, 0, 265, 30);
        fader.center = CGPointMake(70, 515);

        // property of the cell
        cell.volumeSlider = fader;
    }


    // set the slider to 0
    cell.volumeSlider.value = [[self.tracks objectAtIndex:indexPath.row] volume];

    return cell;
}

通过数据模型 ([[tracks objectAtIndex:trackNumber] volume]) 已更新的通知调用以下方法。

- (void) updateVolumeFader:(NSNotification *)note
{
    NSDictionary *extraInfo = [note userInfo];
    int trackNumber = [[extraInfo objectForKey:@"trackNumber"] intValue];
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:trackNumber inSection:0];

    TrackTableCell *cell = (TrackTableCell *)[self.tracksTableView cellForRowAtIndexPath:indexPath];

    cell.volumeSlider.value = [[tracks objectAtIndex:trackNumber] volume]; 
}

在查看代码时,我的猜测是我获取单元格指针的方式。我猜打电话cellForRowAtIndexPath 不是最好的方法。此外,我现在才意识到调用cellForRowAtIndexPath 本身应该将推子更新为tracks 数组中的新值。

正如建议的那样,也许最好保留我所有轨道的滑块(或我的所有单元格,就此而言)的缓存数组。虽然这肯定不是最有效的代码,但我还是不明白为什么它不起作用?

【问题讨论】:

  • 为什么不刷新可见单元格的滑块值而不是重新加载整个表格?滑块是单元格上的属性吗?
  • 是的,滑块值是单元格上的一个属性。但是,在更新属性时,UISlider 的显示值不会更新,直到在主线程上调用 reloadData。此外,AFAIK,reloadData 只是在当前可见的 indexPath 上调用 cellForRowAtIndexPath。
  • 那么,如果在设置滑块值属性时更新滑块值,是否会有所改善?
  • 嗯...不确定我是否遵循“设置滑块值属性时更新滑块值”的意思?这就是我通过调用 myTableCell.mySlider.value 来更新滑块值的方式。这样做不会导致滑块立即更新其位置。为此,我必须在 tableView 上(在主线程上)调用 reloadData。
  • 好的,我误会了你手机的界面。如果滑块是公共属性,那么如果您执行诸如迭代[self.tableView visibleCells] 之类的操作并为每个单元格设置新的滑块值会发生什么?与重新加载表格视图相比,这有什么不同吗?

标签: ios uitableview uislider


【解决方案1】:

如果您的通知没有通过主线程传递,您更新滑块的代码将不起作用。您的通知方法中的代码在其他方面很好;只需将它放在一个块中并在主线程上执行,或者在您注册通知时在主线程(操作队列)上注册。

【讨论】:

  • 太棒了!在主线程上运行一个块就可以了。作为问题的扩展,在回收的表格单元格案例中(正如我正在使用的那样),有没有比调用 cellForRowAtIndexPath 更好的方法来获取适当的单元格指针?
  • 不,这是最好的方法。如果你这样做了,并且单元格不在屏幕上,它会返回 nil,这样你就不会浪费任何时间来更新它。
  • 请注意,向 table 查询 cellForRowAtIndexPath 和向 datasource 查询是有区别的。数据源之一是您自己编写的方法(但不要自己调用)。向表格询问单元格不会命中数据源。
  • 啊……谢谢你的区别。一个非常重要的,我不明白。完美的!感谢您的大力帮助! :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多