UICollectionView:必须使用非nil布局参数初始化


73

UICollectionView通过代码添加。
现在,应用程序崩溃并显示以下消息:UICollectionView must be initialized with a non-nil layout parameter
您有解决的主意吗?
CollectionCell是的自定义类UICollectionViewCell

@property (nonatomic, strong) UICollectionView* collectionView;

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.collectionView = [[UICollectionView alloc]init];
    [self.collectionView registerClass:[CollectionCell class] forCellWithReuseIdentifier:@"cell"];
    UICollectionViewFlowLayout* flowLayout = [[UICollectionViewFlowLayout alloc]init];
    flowLayout.itemSize = CGSizeMake(100, 100);
    [flowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
    [self.collectionView setCollectionViewLayout:flowLayout];

    self.collectionView.frame = CGRectMake(0, 60, 320, 500);
    self.collectionView.backgroundColor = [UIColor whiteColor];
    self.collectionView.delegate = self;
    self.collectionView.dataSource = self;
    [self.view addSubview:self.eventCollection];
}

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return 1;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return 20;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    CollectionCell* cell = [self.eventCollection dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
    cell.label.text = [NSString stringWithFormat:@"%d", indexPath.item];
    return cell;
}

1
为什么要在初始化之前使用self.collectionView?
Marcos Crispino

Answers:


81

崩溃清楚地告诉您出了什么问题:

必须使用非nil布局参数初始化UICollectionView。

如果查看文档UICollectionView,您会发现唯一的初始化程序是initWithFrame:collectionViewLayout:。此外,在该初始化程序的参数中,您将看到:

集合视图的框架矩形,以点为单位。框架的原点与您计划在其中添加的超级视图有关。该帧在初始化期间传递给超类。

布局

用于组织项目的布局对象。集合视图存储对指定对象的强引用。不能为零。

我已经加粗了重要部分。您必须使用initWithFrame:collectionViewLayout:来初始化UICollectionView,并且必须将非nilUICollectionViewLayout对象传递给它。


解决此问题的一种方法就是简单地更改初始化的顺序:

UICollectionViewFlowLayout* flowLayout = [[UICollectionViewFlowLayout alloc] init];
flowLayout.itemSize = CGSizeMake(100, 100);
[flowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
self.collectionView = [[UICollectionView alloc] initWithFrame:self.view.frame collectionViewLayout:flowLayout];
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cell"];

请注意,在上面的示例中,我假设您要self.view.frame用作的框架self.collectionView。如果不是这种情况,请插入所需的任何框架。


45

Swift 3.0和Swift 4.0

UICollectionView

该应用在UICollectionView初始化时启动后便崩溃了

初始化 如下(上方viewDidLoad

let alarmCollectionView:UICollectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: UICollectionViewFlowLayout.init())
let layout:UICollectionViewFlowLayout = UICollectionViewFlowLayout.init()

方法中(内部viewDidLoad

layout.scrollDirection = UICollectionViewScrollDirection.vertical
alarmCollectionView.setCollectionViewLayout(layout, animated: true)
alarmCollectionView.delegate = self
alarmCollectionView.dataSource = self
alarmCollectionView.backgroundColor = UIColor.clear
self.addSubview(alarmCollectionView)

这样初始化后工作正常,我正在使用自动版式,因此请使用CGRect.zero或使用自己的CGRect

UICollectionViewController

如果您使用UICollectionViewController而不是UICollectionView在初始化时需要添加布局

 let  testNavController:UINavigationController = UINavigationController.init()
 let layout:UICollectionViewFlowLayout = UICollectionViewFlowLayout.init() 
 let collectionView:UICollectionViewController = UICollectionViewController.init(collectionViewLayout:layout )              
 testNavController.pushViewController(collectionView, animated: true)

在Swift 4的集合视图控制器内部,您不能使用此方法-会收到错误消息:“无法覆盖类型为'UICollectionView'的可变属性'collectionView'?与协变型'UICollectionView'”
JESSI

我会通知检查,如果更新的答案它不工作的感谢
科希克

更好地保持一个的CollectionView内UIViewController它工作正常,我
科希克

1
let layout:UICollectionViewFlowLayout = UICollectionViewFlowLayout.init() let collectionView:UICollectionViewController = UICollectionViewController.init(collectionViewLayout:layout ) testNavController.pushViewController(collectionView, animated: true)希望这一作品有效
Koushik

24

莱利·阿夫隆Riley Avron)的答案的快速版本

    let layout = UICollectionViewFlowLayout()
    layout.itemSize = CGSizeMake(100, 100)
    let collectionView = UICollectionView(frame: CGRectZero, collectionViewLayout: layout)
    self.view.addSubview(collectionView)
    collectionView.delegate   = self
    collectionView.dataSource = self
    collectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: "cellIdentifier")

5

Swift 5通用解决方案

可以使用UICollectionViewDelegateFlowLayout并且不要忘记设置单元格大小

class YourViewController : UICollectionViewController, UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize.init(width: view.frame.width, height: 250)
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        self.collectionView!.register(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
    }
    // initialized with a non-nil layout parameter
    init() {
        super.init(collectionViewLayout: UICollectionViewFlowLayout())
    }    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

4

Swift 3.0,Swift 4.0和Swift 5.0

对我来说有用。

let collectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: UICollectionViewFlowLayout.init())

在方法中(在viewDidLoad内部)

if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
    flowLayout.scrollDirection = .horizontal
}

无法覆盖类型为'UICollectionView'的可变属性'collectionView'?与协变型“UICollectionView”
阿南德Rockzz

1

在斯威夫特

var collectionView: UICollectionView!
let layout = UICollectionViewFlowLayout()
collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
layout.scrollDirection = .vertical
view.addSubview(collectionView)

0

不要setCollectionViewLayout喜欢此帖:

[self.collectionView setCollectionViewLayout:flowLayout];

尝试在初始化时设置:

[[UICollectionView alloc] initWithFrame:frame collectionViewLayout:defaultLayout];
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.