UICollectionViewを使用してiPhoneのグリッドに画像を表示し、3つの画像を1行に表示したいと思います。 「デッドシンプルテスト」(私が思ったように)のために、プロジェクトに15個のJPG画像を追加しました。これにより、それらはバンドルに含まれ、[UIImage imageNamed:...]から簡単に読み込むことができます。
私はすべてを正しく行ったと思います(UICollectionViewCellサブクラスの設定と登録、UICollectionViewDataSourceプロトコルメソッドの使用)が、UICollectionViewの動作は非常に奇妙です。
次のパターンの画像の一部のみが表示されます。最初の行は画像1と3を示し、2番目の行は空白、次の行は最初のように(画像1と3は正しく表示されます)、4行目は空白などです。 。
[self.collectionView reloadData]をトリガーするNavBarのボタンを押すと、ランダムなセルが表示または非表示になります。私を悩ませているのは、画像が表示されるかどうかだけの問題ではないということです。場合によっては、画像もセル間で入れ替わります。つまり、indexPathに表示され、確実に接続されていません。
セルのコードは次のとおりです。
@interface AlbumCoverCell : UICollectionViewCell
@property (nonatomic, retain) IBOutlet UIImageView *imageView;
@end
@implementation AlbumCoverCell
@synthesize imageView = _imageView;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
_imageView = [[UIImageView alloc] initWithFrame:frame];
[self.contentView addSubview:_imageView];
}
return self;
}
- (void)dealloc
{
[_imageView release];
[super dealloc];
}
- (void)prepareForReuse
{
[super prepareForReuse];
self.imageView.image = nil;
}
@end
UICollectionViewControllerサブクラスのコードの一部。ここで、「imageNames」はすべてのjpgファイル名を保持するNSArrayです。
- (void)viewDidLoad
{
[super viewDidLoad];
[self.collectionView registerClass:[AlbumCoverCell class] forCellWithReuseIdentifier:kAlbumCellID];
}
#pragma mark - UICollectionViewDataSource Protocol methods
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [self.imageNames count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
AlbumCoverCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kAlbumCellID forIndexPath:indexPath];
NSString *imageName = [self.imageNames objectAtIndex:indexPath.row];
NSLog(@"CV setting image for row %d from file in bundle with name '%@'", indexPath.row, imageName);
cell.imageView.image = [UIImage imageNamed:imageName];
return cell;
}
#pragma mark - UICollectionViewDelegateFlowLayout Protocol methods
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath;
{
return CGSizeMake(100, 100);
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section;
{
return UIEdgeInsetsMake(0, 0, 0, 0);
}
CellForItemAtIndexPathのNSLogステートメントから:メソッドがすべてのセル(表示されているセルだけでなく)に対して呼び出され、indexPath.rowとfilenameの間のマッピングが正しいことがわかります。
何がこの奇妙な振る舞いを引き起こす可能性があるのか誰かが考えていますか?
その間に、私は解決策を見つけました。実際、私のUICollectionViewCell
サブクラスAlbumCoverCell
の実装では非常に微妙なエラーでした。
問題は、セルのUIImageView
のboundsプロパティを渡す代わりに、セルインスタンスのフレームをcontentView
サブビューのフレームとして設定したことです。
これが修正です:
@implementation AlbumCoverCell
@synthesize imageView = _imageView;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// WRONG:
// _imageView = [[UIImageView alloc] initWithFrame:frame];
// RIGHT:
_imageView = [[UIImageView alloc] initWithFrame:self.contentView.bounds];
[self.contentView addSubview:_imageView];
}
return self;
}
- (void)prepareForReuse
{
[super prepareForReuse];
// reset image property of imageView for reuse
self.imageView.image = nil;
// update frame position of subviews
self.imageView.frame = self.contentView.bounds;
}
...
@end