2013-06-20 63 views
0

我嘗試在iOS中重新加載UICollectionView時有一個probem。卸載UICollectionView並重新加載?

我使用它來顯示遊戲中的關卡。

collectionview由10個單元組成。單元格的內容取決於級別是否解鎖。如果關卡解鎖,那麼單元顯示關卡(一個自定義的UIView),否則顯示一個圖像。 我不得不爲此創建單獨的單元格標識符,並且所有內容在加載時都完美顯示。

我的問題是當一個用戶正在玩一個解鎖的關卡,然後解鎖下一個關卡。當用戶從遊戲視圖返回到級別選擇視圖時,單元格未正確重新加載(只在自定義視圖應該顯示的位置顯示空白,圖像正確顯示)。

我試圖用viewWillAppear中的級別卸載數組,然後調用[collectionview reloadData] ;,然後加載級別並重新加載collectionview,但這沒有幫助。

如何在顯示視圖時清空整個collectionview並重新創建單元標識符?

謝謝

-EDIT!更新了CODE -

-(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; 

} 
+1

你說的「自定義視圖」是空的,但「圖像正確顯示」 。我不知道如何調和這兩個陳述。但在回答你的問題時,'reloadData'是正確的技術。我會在各種'UICollectionViewDataSource'中放入日誌語句或調試斷點,並確認正在報告正確的值。這個集合視圖最初是否正確工作,但在「解鎖」一個關卡後不正確? – Rob

+0

感謝您的評論羅布。 對不起,任何困惑,但它就像是重新加載時更改的單元格沒有正確更改。 我試圖NSLog的數據,它是正確的。但是,看起來像是當單元格被創建後,一旦它沒有被「重新創建」,就會出現WillAppear。它們在退出視圖並再次打開時正確顯示。所以看起來問題是單元格仍然在內存中而不是重新加載? – CCDEV

+0

通常你會在你的'viewWillAppear'或'viewDidAppear'中編寫代碼,它會調用'reloadData'(在調用'super'後)。爲了重複我自己,我會將log語句放在'numberOfItemsInSection'和'cellForItemAtIndexPath'中,這樣您就可以確認reloadData在視圖重新出現時被正確調用,因此您可以在該點檢查模型結構的各種值。 – Rob

回答

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; 
} 
+0

感謝您的回覆Mundi,但我已經這麼做了。 我已經添加了代碼到我原來的問題,以顯示我在做什麼。我認爲這可能是問題「CVCell * cell =(CVCell *)[collectionView dequeueReusableCellWithReuseIdentifier:[NSString stringWithFormat:@」%@%d「,kCellReuseIdentifier,indexPath.row] forIndexPath:indexPath];」因爲它記住了單元標識符,因此沒有正確地重新加載? – CCDEV

-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; 

}

不是一個非常內存effecient溶液(或優雅),但它的作品。向每個單元格添加一個隨機數字將強制每次重新創建它。只要我只有10個細胞中的CollectionView我認爲這將是確定..

感謝您的幫助:]

+0

這不是一個好的解決方案,至少所有的「修復」。即使現在看來工作,它也一定會突破。您正在cellForItem中創建隨機單元格標識符...請參閱我的修訂答案以獲取解釋。 – Mundi

+0

嗨蒙迪,是的,我知道它現在是一個理想的解決方案。問題是你的答案沒有解決問題。不知道它是否是一個collectionview錯誤,但數據是正確的,但顯示錯誤。這修復了它,因爲單元標識符被重新創建。當我做一個鎖定的解鎖數據的NSLog時,它顯示正確,但不會在[collectiionview reloadData]中重新加載;我不明白爲什麼這會打破?我使用ARC並重新創建單元格不應該成爲問題?性能是唯一的問題,但只有10-15個單元不成問題。 – CCDEV

+0

在這種情況下,創建隨機單元標識符仍然很荒謬。只是不要出隊,而且你有相同的效果。 – Mundi