2

セルが 1 つしかないテーブル ビューがあります。メソッドを呼び出すときに、メソッドを更新しようとすると、テキスト ラベルのテキストが変更されます。ただし、そうではなく、ビューが表示された場合にのみ変更されます。

私は多くの場所で追加NSLog()し、正しいメソッドと条件が呼び出されました

私はいくつかのことを試しました:

reloadData
setNeedsDisplay
setNeedsLayout
reloadCell
reloadRowsAtIndexPaths: withRowAnimation:

しかし、何もUITableViewDataSource機能していません。適切に呼び出されているため、コードに問題がないことはわかっています。

これは私があなたに与えることができる最も適切なコードです:

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

    tableView.scrollEnabled = NO;

    UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier: @"cell"];

    if (cell) {

        cell.selectionStyle = UITableViewCellSelectionStyleNone;

        if ([[TravelLogViewController locationArray] count]) {

            NSDictionary *flight = [NSDictionary dictionaryWithObjectsAndKeys:[[TravelLogViewController locationArray] lastObject], @"name", [[TravelLogViewController dateArray] lastObject], @"date", [[TravelLogViewController milesGainedIndex] lastObject], @"miles", nil];

            cell.detailTextLabel.textColor = [UIColor blackColor];

            cell.textLabel.numberOfLines = 2;
            cell.detailTextLabel.numberOfLines = 2;

            cell.textLabel.font = [UIFont fontWithName:@"Avenir" size: 14.0];
            cell.detailTextLabel.font = [UIFont fontWithName:@"Avenir" size: 12.0];

            cell.selectionStyle = UITableViewCellSelectionStyleNone;

            cell.textLabel.text = [flight objectForKey: @"name"];

            cell.detailTextLabel.text = [NSString stringWithFormat:@"Flight Date: %@, Miles Gained: %.1f", [flight objectForKey: @"date"], [[flight objectForKey: @"miles"] doubleValue]];

            cell.backgroundColor = [UIColor colorWithWhite:0.92 alpha:1];
            //        cell.backgroundColor = [UIColor clearColor];
        }
        else {

// This gets called when I want it to, but the textLabel text or detailTextLabel text is not changed


            cell.detailTextLabel.text = nil;
            cell.textLabel.text = nil;
            cell.textLabel.font = [UIFont fontWithName:@"Arial Rounded MT Bold" size: 18.0];
            cell.textLabel.text = @"\n\n                 No Flights";
        }
    }

    return cell;
}

アップデート:

ARC を使用していますが、セルを更新しようとしたときにテーブル ビューが nil であることがわかりましたが、セルを修正しましたが、その理由がわかりません!?

テーブルビューをどこにも解放したり解放したりしていません。まだ割り当てられているはずです

ちなみに私はタブバーコントローラーを持っています

アップデート:

賞金を開始しました.1週間以上経ちましたnil.

アップデート:

わかりました、ユーザーがスワイプしてセルを削除できることを忘れていました。彼がそうすると、実際にセルを削除するのではなく、テキストを変更するだけです (つまり、更新されていない部分です)。ログを入力すると、ユーザーがスワイプして削除するviewDidLoadviewDidAppear、テーブルビューが有効であるように見えます...これが私のコードです:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

if (editingStyle == UITableViewCellEditingStyleDelete) {

    TravelLogViewController *travel = [[TravelLogViewController alloc] init];
    [travel manuallyDeleteTopCellData]; // Deletes some data in other view controller and calls the method `proceedWithDeletion`
}
}
- (void)proceedWithDeletion {

// Method is called from another view controller

NSLog(@"%@", mostRecentFlight.description); // NIL HERE

[mostRecentFlight reloadData];
[mostRecentFlight setNeedsDisplay];
[mostRecentFlight setNeedsLayout];

}

TravelLogViewController

- (void)manuallyDeleteTopCell {

[TheMileIndexViewController deductDesiredMilesToIndex: [[milesGainedIndex lastObject] floatValue]];

[locationArray removeLastObject];

[milesGainedIndex removeLastObject];

[dateArray removeLastObject];

MenuMileIndexViewController *menu = [[MenuMileIndexViewController alloc] init];
[menu proceedWithDeletion];

}

要約すると、ビューがロード/表示されると、テーブルビューは有効になります。ユーザーがスワイプして削除すると、実際には行が削除されず、TravelLogViewControllerメソッドと呼ばれる別のビューコントローラーが呼び出されmanuallyDeleteTopCellData、データが削除され、そのメソッドが元のビューコントローラーで別のメソッドが呼び出されproceedWithDeletion、テーブルビューをリロードするはずの場所で呼び出されます、しかしそうではありません(問題)。この理由はproceedWithDeletion、テーブル ビューでは nil だからですが、なぜ!?

4

8 に答える 8

3

何もコードを書かないブラインドショットですが、 を使用dequeueReusableCellWithIdentifierすると問題が発生する可能性があります。セルが 1 つある場合は、作成済みのセルcellForRowAtIndexPathを再利用する代わりに、毎回作成できます。このような小さなテーブルではパフォーマンスに影響しません

于 2012-10-05T09:08:48.610 に答える
2

問題があなたが探している、または説明している領域にないことはほぼ確認できます。

サンプル プロジェクトをゼロから作成しました。ごく最小限に、aUITableViewと aUIButtonをトリガーし[table reloadData]てブール値を反転させるだけです。

BOOL toggle = NO;

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 1;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier: @"cell"];

    if (cell) {

        cell.selectionStyle = UITableViewCellSelectionStyleNone;

        if (toggle )
        {
            NSDictionary *flight = @{@"name" : @"Bob",
                                 @"date" : @"Yesterday",
                                 @"miles" : @"3" };

            cell.textLabel.text = [flight objectForKey: @"name"];
            cell.textLabel.numberOfLines = 2;

            cell.detailTextLabel.numberOfLines = 2;
            cell.detailTextLabel.textColor = [UIColor blackColor];
            cell.detailTextLabel.text = [NSString stringWithFormat:@"Flight Date: %@, Miles Gained: %.1f", [flight objectForKey: @"date"], [[flight objectForKey: @"miles"] doubleValue]];

        } else {

            cell.textLabel.text = @"blank label";
            cell.detailTextLabel.text = @"blank detail";
        }
    }
    return cell;
}

- (IBAction)toggleValue:(id)sender
{
    toggle = !toggle;
    NSLog( @"toggle is now %@", (toggle) ? @"YES" : @"NO" );

    [tv reloadData];
}

でブール値を参照し、指定したコードを使用すると、が呼び出さtableView:cellForRowAtIndexPath:れたときに行が実際に期待どおりに更新されることがわかります。[table reloadData]

ここからサンプル プロジェクトをダウンロードできます (35KB): http://rdas.me/SampleProject.zip

これがお役に立てば幸いです。他に何もないとしても、実際に問題が存在する場所を特定するのに役立ちます。

幸運を!

于 2012-10-15T20:43:14.117 に答える
1

このコードが問題の原因である可能性があります。

MenuMileIndexViewController *menu = [[MenuMileIndexViewController alloc] init];
[menu proceedWithDeletion];

あなたは、MenuMileIndexViewController既存のインスタンスにアクセスするのではなく、まったく新しい を作成しています。これは、あなたがやりたいことだと思います。この新しいインスタンスは、 に保存されている元のテーブル ビューにアクセスできませんmostRecentFlight。内部では、呼び出し元のインスタンス-manuallyDeleteTopCellへの参照が必要です。MenuMileIndexViewController

selfそれは、その変数に渡して-manuallyDeleteTopCellData使用して、後で呼び出すのと同じくらい簡単かもしれません-proceedWithDeletion。例えば:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        TravelLogViewController *travel = [[TravelLogViewController alloc] init];
        [travel manuallyDeleteTopCellData:self];
    }
}

- (void)manuallyDeleteTopCell:(id)sender {
    [TheMileIndexViewController deductDesiredMilesToIndex: [[milesGainedIndex lastObject] floatValue]];
    [locationArray removeLastObject];
    [milesGainedIndex removeLastObject];
    [dateArray removeLastObject];
    // MenuMileIndexViewController *menu = [[MenuMileIndexViewController alloc] init];
    [sender proceedWithDeletion];
}
于 2012-10-16T05:48:02.590 に答える
1

の実装では、この時点でnew をインスタンス化manuallyDeleteTopCellします。TravelLogViewControllerMenuMileIndexViewController

MenuMileIndexViewController *menu = [[MenuMileIndexViewController alloc] init];
[menu proceedWithDeletion];

これは別のコントローラーであり、適切に初期化されておらず、画面上のビューにも関与していません。mostRecentFlight特に、同じプロパティはありません。が元のコントローラを呼び出すには、次のようTravelLogViewControllerにパラメータとして渡してmanuallyDeleteTopCellコールバックする必要があります。

- (void)manuallyDeleteTopCell:(MenuMileIndexViewController *)origin {
    [TheMileIndexViewController deductDesiredMilesToIndex: [[milesGainedIndex lastObject] floatValue]];

    [locationArray removeLastObject];
    [milesGainedIndex removeLastObject];
    [dateArray removeLastObject];

    [origin proceedWithDeletion];
}

そして、呼び出しコードを次のように書き直します。

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        TravelLogViewController *travel = [[TravelLogViewController alloc] init];
        [travel manuallyDeleteTopCellData:self];
}

以前の提案:

  1. Interface Builder でアウトレットが正しく設定されていることを確認してください。コメントでこれを行ったと言っていますが、別の時点で、タブバーコントローラーを使用していると言っています。UIViewController現在表示されており、使用しているインスタンスのviewControllersプロパティに含まれている通常のView Controller(つまり、のサブクラス)でアウトレットを設定していることを確認してください。サブクラス化しないでください(明示的に禁止しているApple のドキュメントを参照してください)。[チェック済み]UITabBarControllerUITabBarController

  2. viewDidLoad通常のビュー コントローラーのメソッドと、このメソッドが呼び出されたときに非であることを確認NSLogするself.tableViewプロパティを実装します。[チェック済み]nil

  3. @synthesize mostRecentFlight = _mostRecentFlight;の にステートメントを記述し、の@implementationプロパティTravelLogViewControllerにブレークポイントを設定します@interfacesetMostRecentFlight:または、プロパティのメソッドを手動で実装し、mostRecentFlightこのメソッド内にブレークポイントを設定します。プロパティが に設定されている時間を見つけるのに役立つセッターが呼び出されると、このブレークポイントがトリガーされnilます。

  4. viewDidLoad手順 2 のメソッドでプロパティが非 nil であると仮定して、オブジェクトのアドレス (アドレス(UITableView *) $1 = 0xXXXXXXXXであると言う記述の先頭0xXXXXXXXX) を見てください。コードの後半でオブジェクトを使用する場所 (プロパティが nil の場合) にブレークポイントを設定します。デバッガーで入力しますpo 0xXXXXXXXX(上記の適切なアドレスを使用)。あなたが得る応答は何ですか?

于 2012-10-15T19:55:18.637 に答える
0

あなたのコードには何も問題がありません。ただし、テーブル ビューのデータ ソースとデリゲートを次のように設定してください (viewDidLoad/viewDidAppear/viewWillAppear のどこかに設定する必要があります)。

[tableView setDelegate:self];
[tableView setDataSource:self];

この後、表示する必要がある行数をデリゲート メソッドから返すようにしてください。

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return [yourDataSource count];
}

頑張ってください!

于 2012-10-12T16:53:24.307 に答える
0

私は通常、このコードを使用します:

[_myTable beginUpdates];

[... update my cell, adding / removing / changing them ...];

[_myTable endUpdates];

バージョン 5.0 以降のプロジェクトで動作します。

于 2012-10-05T09:03:08.447 に答える
0

あなたのコメントによると、あなたtableViewが呼び出した変数reloadDatanil.

これの一般的な理由は、nib を使用する場合の IBOutlet へのリンクの欠落、ARC による弱い ivar、または同じ名前のローカル変数で ivar をマスクすることです。

于 2012-10-05T13:05:42.523 に答える
0

注意したいです。ストーリーボードを使用している場合は、セルを割り当てる必要はありません。このコードで十分です:

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

UITableViewCell *cell = [tableView 
  dequeueReusableCellWithIdentifier:@"PlayerCell"];
Player *player = [self.players objectAtIndex:indexPath.row];
cell.textLabel.text = player.name;
cell.detailTextLabel.text = player.game;
return cell;

}

于 2012-10-16T05:06:57.727 に答える