0

シンプルなタイマーアプリを作っています。複数の行を持つ uitable があります。そのテーブルに UIButton を配置しました。すべてが機能し、これまでのところ非常に良好です。つまり、各行にボタンが表示されます。次に必要だったのは、UIButton のイメージを設定することでした。たとえば、タイマーが実行されている場合は UIButton に stop_button_image を表示し、タイマーが開始した場合はボタンの UIImage を start_button_image に設定したいと考えていました。

問題は、テーブルが更新されると、UIButton setimage コードを配置した場所に応じて、厄介なトレースバックが発生することです。参照用の私のコードは次のとおりです。

//WORKING CODE: (NOT THAT I WANT)
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        //TESTING - Button
        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];

        // Try to retrieve from the table view a now-unused cell with the given identifier.
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

        // If no cell is available, create a new one using the given identifier.
        if (cell == nil)
        {
            // Use the default cell style.
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];

            //TESTING - Button
            [button addTarget:self
                       action:@selector(timerStopStart:)
             forControlEvents:UIControlEventTouchDown];
            [button setTitle:@"Start/Stop" forState:UIControlStateNormal];
            button.frame = CGRectMake(5.0f, 5.0f, 72.0f, 77.0f);
            button.tag = indexPath.row;
            [cell addSubview:button];

    //THIS WORKS IF I PUT THIS HERE
            [button setImage:[UIImage imageNamed:@"button_pause.png"] forState:UIControlStateNormal];

        }
        else 
        {
             //NSLog(@"went here 2");
             button = (UIButton *) [cell viewWithTag:indexPath.row];
        }

//some other logic
    }

//ここでコードブレイク

        - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
        {
            //TESTING - Button
            UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];

            // Try to retrieve from the table view a now-unused cell with the given identifier.
            UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

            // If no cell is available, create a new one using the given identifier.
            if (cell == nil)
            {
                // Use the default cell style.
                cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];

                //TESTING - Button
                [button addTarget:self
                           action:@selector(timerStopStart:)
                 forControlEvents:UIControlEventTouchDown];
                [button setTitle:@"Start/Stop" forState:UIControlStateNormal];
                button.frame = CGRectMake(5.0f, 5.0f, 72.0f, 77.0f);
                button.tag = indexPath.row;
                [cell addSubview:button];


            }
            else 
            {
                 //NSLog(@"went here 2");
                 button = (UIButton *) [cell viewWithTag:indexPath.row];
            }

//CODE BREAKS HERE
[button setImage:[UIImage imageNamed:@"button_pause.png"] forState:UIControlStateNormal];

    //some other logic
        }

問題は、テーブルが更新されると、コード ボタン = (UIButton *) [cell viewWithTag:indexPath.row]; でセクションが呼び出されることです。私が知っているのは単なる参考です。

iOSシミュレーターで発生するエラーは次のとおりです。その画像コードを cell==null チェックの外に置きたいと思っています。これを行う方法の手がかりはありますか?

シミュレーターで発生するエラーは次のとおりです

2012-06-14 12:39:27.246 Timers[5381:10a03] -[UITableViewCell setImage:forState:]: unrecognized selector sent to instance 0x73706e0
2012-06-14 12:39:27.247 Timers[5381:10a03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITableViewCell setImage:forState:]: unrecognized selector sent to instance 0x73706e0'
*** First throw call stack:
(0x150b052 0x16bbd0a 0x150cced 0x1471f00 0x1471ce2 0x136c6 0x7b5e0f 0x7b6589 0x7a1dfd 0x7b0851 0x75b322 
4

2 に答える 2

2

問題は、おそらく indexPath.row がゼロの場合です。その場合、呼び出しますviewWithTag:0が、UIView のタグはデフォルトで 0 であるため、UIButton だけでなく、多くのセルのサブビューに値 0 のタグがある可能性があります。

この問題を回避するには、タグに影響を与える前に定数 (100 など) を indexPath.row に追加してみてください。これにより、行 0 のボタンに 0 ではなくタグ 100 が設定されます (行 1 のボタンにタグが設定されます)。 101 など…)、タグ 0 を持つ他のサブビューと混同されるのを防ぎます。

于 2012-06-14T16:51:08.627 に答える
1

ええ、これは行 0 では失敗します。

button = (UIButton *) [cell viewWithTag:indexPath.row];

cell.tag が 0 であるため、indexPath.row が 0 の場合は cell を返します。


一般的な注意として、このアプローチは機能しません。セルを初めて再利用すると、ボタンに間違ったタグが付けられます。たとえば、行 2 のセルを行 18 で再利用すると、ボタンのタグは 2 になりますが、探しているタグは 18 ですnil

定数を定義して、#define kMyStopStartButtonTag 12345その定数をずっと使用してみませんか。

if (cell == nil)
{
    …
    button.tag = kMyStopStartButtonTag;
    [cell addSubview:button];
    …
} else {
    button = (UIButton *) [cell viewWithTag:kMyStopStartButtonTag];
}
于 2012-06-14T16:51:21.310 に答える