使用 Objective C 在 iOS 中正确创建 uicollection 视图

Correctly create uicollection view in iOS using Objective C

提问人:Jobalisk 提问时间:11/16/2023 最后编辑:Jobalisk 更新时间:11/19/2023 访问量:39

问:

我一直在尝试让集合视图在 iOS 中正常工作。 我一直在关注这个问题:如何创建自定义 UICollectionViewCell

我认为我的大部分都是正确的,我正在使用教程自定义单元格类(请参阅代码的链接),但是当我使用集合视图访问视图控制器时,我总是遇到错误。

这是我的代码:

#import "BackPackController.h"
#import "UICollectionViewCell+CollectionViewCell.h"

@interface BackPackController () <UICollectionViewDelegate, UICollectionViewDataSource>

@end

@implementation BackPackController

NSArray *itemArray; //our item array

- (void)viewDidLoad {
    [super viewDidLoad];
    itemArray = [[NSUserDefaults standardUserDefaults] objectForKey:@"PlayerItems"]; //get the players items from the user defaults and make an array of them
    _itemGrid.delegate = self;
    _itemGrid.dataSource = self;
    //[_itemGrid setDataSource:self];
    //[_itemGrid registerClass:CollectionViewCell.self forCellWithReuseIdentifier:@"cell1"];

}


- (nonnull __kindof UICollectionViewCell *)collectionView:(nonnull UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath {
    NSLog(@"Got this far");
    CollectionViewCell *cell1 = [_itemGrid dequeueReusableCellWithReuseIdentifier:@"cell1" forIndexPath:indexPath];
    [cell1.customLabel setText:itemArray[indexPath.row]];
    return cell1;
    
}



- (NSInteger)collectionView:(nonnull UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 
    return itemArray.count;
    
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:   (UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
    return CGSizeMake(100, 100);
}

据我所知,我已经正确地将控制器附加为委托和数据源。上面代码中的 NSLog 确实打印了它的消息,所以我知道正在调用 cellForItemAtIndexPath 方法。但是,一旦调用它,我就会返回此错误,并且我正在努力准确了解导致它的原因:

2023-11-16 08:36:19.163928+1300 Matoran Quest[7698:1793467] *** Assertion failure in -[UICollectionView _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes:isFocused:notify:], UICollectionView.m:3389
2023-11-16 08:36:19.164525+1300 Matoran Quest[7698:1793467] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'the collection view's data source returned nil from -collectionView:cellForItemAtIndexPath: for index path <NSIndexPath: 0x8db3e297ef8cf73e> {length = 2, path = 0 - 0}'

正在访问的列表是一个简单的字符串列表,我知道它运行正常,因为我在其他地方访问它没有问题。我尝试将添加到单元格中的文本更改为仅@“test”,但这没有任何改变

iOS Objective-C UIColictionView

评论

0赞 Teja Nandamuri 11/16/2023
您是否检查过cellForItem方法中是否为null?cell1
1赞 Mykyta iOS 11/16/2023
_itemGrid是否依附于其 IBOutlet?我注意到您正在使用 ivar 对单元格进行排队:CollectionViewCell *cell1 = [_itemGrid dequeueReusableCellWithReuseIdentifier:@“cell1” forIndexPath:indexPath];,通常通过引用委托方法中的 collectionView 参数来完成,例如: CollectionViewCell *cell1 = [collectionView dequeueReusableCellWith...如果您的集合在 NIB 中设置了 dataSource,但它未附加到 itemGrid 出口,则您的“单元格数”将返回正确的计数,但从 nil 集合中出列将导致 nil 单元格
0赞 HangarRash 11/16/2023
您注释掉了用于将单元格类注册到集合视图的行。你需要那条线。
0赞 Jobalisk 11/16/2023
当我没有注释掉它时,它会失败并出现符号错误
0赞 Jobalisk 11/16/2023
我无法将网格附加到 iboutlet,因为它不允许我。我现在已经走了,让它只是一个常规变量。你能回答这个问题,你将如何以编程方式设置它 Mykyta iOS?

答:

2赞 DonMag 11/17/2023 #1

从简单开始...

使用以下代码:


UICollectionViewCell+CollectionViewCell.h - *注意:不知道你为什么这样命名你的文件......通常,“类+名称”用于类别...但是,假设类中的代码如下所示:

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface CollectionViewCell : UICollectionViewCell
@property (strong, nonatomic) IBOutlet UILabel *customLabel;
@end

NS_ASSUME_NONNULL_END

UICollectionViewCell+CollectionViewCell.m

#import "UICollectionViewCell+CollectionViewCell.h"

@implementation CollectionViewCell

@end

BackPackController.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface BackPackController : UIViewController
@property (strong, nonatomic) IBOutlet UICollectionView *itemGrid;
@end

NS_ASSUME_NONNULL_END

BackPackController.m(BackPack控制器.m)

#import "BackPackController.h"
#import "UICollectionViewCell+CollectionViewCell.h"

@interface BackPackController () <UICollectionViewDelegate, UICollectionViewDataSource>

@end

@implementation BackPackController

NSMutableArray *itemArray;

- (void)viewDidLoad {
    [super viewDidLoad];
    
    itemArray = [NSMutableArray new];
    
    // let's generate a simple string array
    for (int i = 0; i < 40; i++) {
        NSString *s = [NSString stringWithFormat:@"%i", i];
        [itemArray addObject:s];
    }
    
    _itemGrid.dataSource = self;
    _itemGrid.delegate = self;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return itemArray.count;
}

- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    CollectionViewCell *c = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell1" forIndexPath:indexPath];
    [c.customLabel setText:itemArray[indexPath.item]];
    return c;
}

@end

现在,在 Storyboard 中,添加一个并将其类分配给UIViewControllerBackPackController

将单元格 Prototype 的类分配给 ,并将其标识符设置为“cell1”(不带引号)。CollectionViewCell

添加 a 并在所有 20 个边上用 4 个点对其进行约束。给它和它的默认单元格对比背景颜色,这样我们就可以看到它。UICollectionView

将 a 添加到单元原型中,并将其约束为居中。UILabel

连接到单元格中的标签。IBOutlet UILabel *customLabel

连接到控制器中的集合视图。IBOutlet UICollectionView *itemGrid

应该看起来像这样(忽略我在故事板中的其他控制器):

enter image description here

运行应用时,应看到以下内容:

enter image description here

现在你可以开始在UserDefaults中实现你的“PlayerItems”,添加你的搜索栏,等等。

0赞 Jobalisk 11/19/2023 #2

好的,弄清楚了为什么会发生这种情况,而且有点愚蠢。我有一个搜索栏附加到我的集合视图,但我无法正确地将视图分配为出口,因为每当我将视图控制器拖动到我的集合视图时,它都会尝试附加到搜索栏而不是集合视图。当然,我没有搜索栏的出口,所以它一直显示没有任何可附加的内容,结果,因为它没有附加,代码无法正常工作。我删除了搜索栏并正确连接了它,然后它工作正常。谢谢你的帮助,虽然伙计们。