UICollectionView: muss mit einem Layoutparameter ungleich Null initialisiert werden

73

Ich habe UICollectionViewper Code hinzugefügt .
Jetzt stürzt die App mit Meldung ab : UICollectionView must be initialized with a non-nil layout parameter.
Haben Sie eine Idee, um das Problem zu beheben?
CollectionCellist benutzerdefinierte Klasse von 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;
}
kusumoto_teruya
quelle
1
Warum verwenden Sie self.collectionView, bevor Sie es initialisieren?
Marcos Crispino

Antworten:

81

Der Absturz sagt Ihnen ziemlich explizit, was falsch läuft:

UICollectionView muss mit einem Layoutparameter ungleich Null initialisiert werden.

Wenn Sie in der Dokumentation nachsehenUICollectionView , werden Sie feststellen, dass der einzige Initialisierer ist initWithFrame:collectionViewLayout:. In den Parametern für diesen Initialisierer sehen Sie außerdem:

Rahmen

Das Rahmenrechteck für die Sammlungsansicht, gemessen in Punkten. Der Ursprung des Frames ist relativ zu der Übersicht, in der Sie ihn hinzufügen möchten. Dieser Frame wird während der Initialisierung an die Oberklasse übergeben.

Layout

Das Layoutobjekt, das zum Organisieren von Elementen verwendet werden soll. In der Sammlungsansicht wird ein starker Verweis auf das angegebene Objekt gespeichert. Darf nicht null sein.

Ich habe den wichtigen Teil gewagt . Sie müssen verwenden initWithFrame:collectionViewLayout:, um Ihr Objekt zu initialisieren UICollectionView, und Sie müssen ihm ein Nicht-Null- UICollectionViewLayoutObjekt übergeben.


Eine Möglichkeit, dies zu beheben, besteht darin, einfach die Reihenfolge Ihrer Initialisierung zu ändern:

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

Beachten Sie, dass ich im obigen Beispiel davon ausgegangen bin, dass Sie self.view.frameals Frame von verwenden möchten self.collectionView. Wenn dies nicht der Fall ist, fügen Sie stattdessen den gewünschten Rahmen ein.

Ravron
quelle
45

Swift 3.0 und Swift 4.0

UICollectionView

Die App stürzte ab, sobald sie bei der UICollectionViewInitialisierung gestartet wurde

initialisiere wie unten (oben viewDidLoad)

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

In Methode (innen viewDidLoad)

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

Hat nach dieser Initialisierung gut funktioniert. Ich verwende Autolayout, also benutze CGRect.zerooder benutze dein eigenesCGRect

UICollectionViewController

Falls Sie UICollectionViewControllerstattdessen verwenden UICollectionView, müssen Sie bei der Initialisierung ein Layout hinzufügen

 let  testNavController:UINavigationController = UINavigationController.init()
 let layout:UICollectionViewFlowLayout = UICollectionViewFlowLayout.init() 
 let collectionView:UICollectionViewController = UICollectionViewController.init(collectionViewLayout:layout )              
 testNavController.pushViewController(collectionView, animated: true)
Koushik
quelle
Innerhalb eines Sammlungsansichts-Controllers in Swift 4 können Sie diese Methode nicht verwenden. Es wird die Fehlermeldung "Die veränderbare Eigenschaft 'collectionView' vom Typ 'UICollectionView?' Kann nicht überschrieben werden." mit kovarianten Typ 'UICollectionView' "
Jessi
Ich werde die Antwort überprüfen und aktualisieren, wenn sie nicht funktioniert. Danke für die Benachrichtigung
Koushik
Es ist besser, eine Sammlungsansicht in einem zu behalten, UIViewControlleres funktioniert gut für mich
Koushik
1
let layout:UICollectionViewFlowLayout = UICollectionViewFlowLayout.init() let collectionView:UICollectionViewController = UICollectionViewController.init(collectionViewLayout:layout ) testNavController.pushViewController(collectionView, animated: true)Hoffe, dass dies funktioniert
Koushik
24

Nur eine schnelle Version von Riley Avrons Antwort

    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")
William Hu
quelle
5

Swift 5 allgemeine Lösung

Kann UICollectionViewDelegateFlowLayout verwenden und vergessen Sie nicht, Ihre Zellengröße festzulegen

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")
    }
}
Candyline
quelle
4

Swift 3.0, Swift 4.0 und Swift 5.0

Es ist Arbeit für mich.

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

In Methode (in viewDidLoad)

if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
    flowLayout.scrollDirection = .horizontal
}
John Corder
quelle
Kann die veränderbare Eigenschaft 'collectionView' vom Typ 'UICollectionView' nicht überschreiben? mit kovariantem Typ 'UICollectionView'
Anand Rockzz
1

In Swift

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

setCollectionViewLayout hat das nicht gefallen:

[self.collectionView setCollectionViewLayout:flowLayout];

versuche zu setzen wann init:

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