0

iOS で UICollectionview をリロードしようとすると問題が発生します。

ゲームのレベル表示に使用しています。

コレクションビューは 10 個のセルで構成されています。セルの内容は、レベルがロック解除されているかどうかによって異なります。レベルのロックが解除されている場合、セルはレベル (カスタム UIView) を表示し、それ以外の場合は画像を表示します。これを機能させるには、個々のセル識別子を作成する必要があり、ロード時にすべてが完全に表示されます。

私の問題は、ユーザーがロックされていないレベルをプレイしていて、次のレベルのロックを解除したときです。ユーザーがゲーム ビューからレベル選択ビューに戻ると、セルが正しくリロードされません (カスタム ビューがあるべき場所に空白が表示され、画像が正しく表示されます)。

viewWillAppear のレベルで配列をアンロードしてから [collectionview reloadData]; を呼び出し、レベルをロードしてコレクションビューを再度リロードしようとしましたが、それは役に立ちません。

コレクションビュー全体を空にして、ビューが表示されたときにセル識別子を再作成するにはどうすればよいですか?

ありがとう

-編集!コードで更新 -

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

levelsArray = nil;
puzzlesArray = nil;

levelsArray = [[NSMutableArray alloc]init];
puzzlesArray = [[NSMutableArray alloc]init];

[collectionView reloadData];

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *data = [defaults objectForKey:@"puzzles"];
puzzlesArray = [NSKeyedUnarchiver unarchiveObjectWithData:data];

if ([puzzlesArray count] == 0) {
    [self.navigationController popViewControllerAnimated:YES];
}
else {
    NSLog(@"%i puzzles loaded", [puzzlesArray count]);

    //Get alle puzzles for the current category
    for (Puzzle *puzzle in puzzlesArray) {

        if ([[[NSUserDefaults standardUserDefaults]objectForKey:@"Category"] isEqualToString:[puzzle categoryName]]) {
            [levelsArray addObject:puzzle];
        }

    }

}

NSLog(@"View will appear");
[collectionView reloadData];

}

そして、インデックスパスのアイテムのセル

    - (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath; {

    BOOL isUnlocked = [self isPuzzleUnlocked:[indexPath row]];

    if ([[NSUserDefaults standardUserDefaults]boolForKey:@"u"] == YES) {
        isUnlocked = YES;
    }

    [self.collectionView registerNib:[UINib nibWithNibName:@"CVCell" bundle:nil] forCellWithReuseIdentifier:[NSString stringWithFormat:@"%@%d", kCellReuseIdentifier, indexPath.row]];

    CVCell *cell = (CVCell *)[collectionView dequeueReusableCellWithReuseIdentifier:[NSString stringWithFormat:@"%@%d", kCellReuseIdentifier, indexPath.row] forIndexPath:indexPath];

[cell setPuzzleInfo:[levelsArray objectAtIndex:[indexPath row]] unlocked:isUnlocked];

        return cell;

}
4

2 に答える 2

1

ロブの提案に沿って。

-(void)viewWillAppear {
   [super viewWillAppear];
   [self.collectionView reloadData]; 
}

cellForItemAtIndexPathアイテムのロックが解除されているかどうかを確認し、適切な画像またはカスタム セルを表示するだけです。

それで全部です。コレクション ビューを再作成する必要はまったくありません。

ゲーム コントローラーとレベル コントローラーの両方に、レベルをモデル化するデータへのアクセスを許可することで、MVC (モデル ビュー コントローラー) デザイン パターンを尊重したい場合があります。ゲームで起こっていることが新しいレベルのロックを解除すると、このデータが変更されます。コレクション ビューは、表示される直前にこのデータに基づいて再読み込みする必要があります。

編集:

にもかかわらず、以前と同じセル/アイテムを取得する場合reloadData、これは構成が正しく設定されていないことを意味します。重要なのは、両方の状態unlocked 明示的に設定reloadDataすることです。変更された場合はアイテムを更新します。

EDIT2:

どちらのitemForRowAtIndexPath方法も台無しです。への呼び出しregisterNibはそこにまったく属していません! 初期化プロセス中に呼び出されることになっています。ストーリーボードを使用する場合は、まったく必要ありません。

以下は、使用すべき単純なフレームワークです。

- (UICollectionViewCell *)collectionView:(UICollectionView *)cv 
                  cellForItemAtIndexPath:(NSIndexPath *)indexPath; {

   PuzzleInfo *puzzleObject = [dataArray objectAtIndex:indexPath.row]; 
   // you can use your more complicated data structure here, but 
   // have one object, dictionary, array item, etc. that has the info you need

   NSString *identifier = puzzleObject.unlocked ? kUnlockedCell : kLockedCell;
   CVCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier
           forIndexPath:indexPath];

   if (puzzleObject.unlocked) {
      // configure the unlocked cell 
   }
   else {
      // configure the locked cell
   }

   return cell;
}
于 2013-06-20T16:23:33.557 に答える
-3

それを私が直した!

- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath; {
NSLog(@"CALLED");
BOOL isUnlocked = [self isPuzzleUnlocked:[indexPath row]];

if ([[NSUserDefaults standardUserDefaults]boolForKey:@"u"] == YES) {
    isUnlocked = YES;
}
int rand = arc4random() % 99001;
[self.collectionView registerNib:[UINib nibWithNibName:@"CVCell" bundle:nil] forCellWithReuseIdentifier:[NSString stringWithFormat:@"%@%d%i", kCellReuseIdentifier, indexPath.row, rand]];

CVCell *cell = (CVCell *)[collectionView dequeueReusableCellWithReuseIdentifier:[NSString stringWithFormat:@"%@%d%i", kCellReuseIdentifier, indexPath.row, rand] forIndexPath:indexPath];
[cell setPuzzleInfo:[levelsArray objectAtIndex:[indexPath row]] unlocked:isUnlocked];

    return cell;

}

非常にメモリ効率の良い(またはエレガントな)ソリューションではありませんが、機能します。各セルに乱数を追加すると、毎回強制的に再作成されます。コレクションビューにセルが10個しかない限り、問題ないと思います..

ご助力いただきありがとうございます :]

于 2013-06-21T06:22:58.753 に答える