3

UISliderを「オーディオVUメーター」タイプのインジケーターとして使用したいと考えています。この場合、オーディオトラックのレベルによってUISliderの値が継続的に更新されます。私のアプリケーションの各トラックは現在UITableViewCellとして配置されており、VUメーターはセルのコンテンツビュー内の1つのサブビューです。一度に最大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

提案されているように、おそらく、すべてのトラックのスライダー(または、さらに言えば、すべてのセル)のキャッシュされた配列を保持するのが最善です。これは確かに最も効率的なコードではありませんが、なぜそれが機能しないのかまだわかりませんか?

4

1 に答える 1

1

メインスレッドで通知が届かない場合、スライダーを更新するコードは機能しません。それ以外の場合、通知メソッドのコードは問題ありません。ブロック内に配置してメインスレッドで実行するか、通知登録時にメインスレッド(操作キュー)に登録するだけです。

于 2012-08-31T05:58:52.520 に答える