【问题标题】:UICollectionView: must be initialized with a non-nil layout parameterUICollectionView:必须用非零布局参数初始化
【发布时间】:2014-08-08 22:45:36
【问题描述】:

我通过代码添加了UICollectionView
现在,应用程序崩溃并显示消息:UICollectionView must be initialized with a non-nil layout parameter.
你有什么解决办法吗?
CollectionCellUICollectionViewCell 的自定义类。

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

【问题讨论】:

  • 为什么在初始化之前使用self.collectionView?

标签: ios uicollectionview


【解决方案1】:

崩溃非常明确地告诉您出了什么问题:

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

如果你检查the documentation for UICollectionView,你会发现唯一的初始化器是initWithFrame:collectionViewLayout:。此外,在该初始化程序的参数中,您会看到:

框架

集合视图的框架矩形,以磅为单位。框架的原点是相对于您计划在其中添加它的超级视图。此帧在初始化期间传递给超类。

布局

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

我已经加粗了重要的部分。你必须使用initWithFrame:collectionViewLayout: 来初始化你的UICollectionView,并且你必须传递一个非零的UICollectionViewLayout 对象。


因此,解决此问题的一种方法是简单地更改您执行的初始化顺序:

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 的框架。如果不是这种情况,请插入您想要的任何框架。

【讨论】:

    【解决方案2】:

    只是 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")
    

    【讨论】:

      【解决方案3】:

      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)
      

      像这样初始化后工作正常我正在使用 Autolayout 所以使用 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'"
      • 我会检查并更新答案,如果它不起作用感谢通知
      • 最好将 collectionview 保存在 UIViewController 中,这对我来说效果很好
      • let layout:UICollectionViewFlowLayout = UICollectionViewFlowLayout.init() let collectionView:UICollectionViewController = UICollectionViewController.init(collectionViewLayout:layout ) testNavController.pushViewController(collectionView, animated: true)希望这个有用
      【解决方案4】:

      不要 setCollectionViewLayout 喜欢这个:

      [self.collectionView setCollectionViewLayout:flowLayout];
      

      尝试在初始化时设置:

      [[UICollectionView alloc] initWithFrame:frame collectionViewLayout:defaultLayout];
      

      【讨论】:

        【解决方案5】:

        在斯威夫特中

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

        【讨论】:

          【解决方案6】:

          Swift 3.0、Swift 4.0 和 Swift 5.0

          这对我有用。

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

          In 方法(在 viewDidLoad 内)

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

          【讨论】:

          • 无法覆盖“UICollectionView”类型的可变属性“collectionView”?具有协变类型“UICollectionView”
          【解决方案7】:

          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")
              }
          }
          

          【讨论】:

            猜你喜欢
            • 2019-09-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-05-09
            • 1970-01-01
            • 2019-01-19
            • 1970-01-01
            • 2017-04-08
            相关资源
            最近更新 更多