UICollectionCell method to call in CollectionViewController

I have a standard view controller that contains a collection view.

I populate the collection view with custom cells created from a custom subclass of UICollectionViewCell .

  • What is the best practice of calling a method in a collection view class from a collection view cell class

  • Why the next init is not called in my collection socket class, I thought it would be called when the collectionView class creates my cells.

    (id)initWithFrame:(CGRect)frame

The reason I want to do this is because I delete the collection view cell, the delete function is inside the collection view cell class. I want to play the sound when it deletes, and would rather include the / s sound in the collection controller class, rather than for each cell.

+4
ios uicollectionviewcell
source share
2 answers

By default, the UICollectionViewCell does not have a reference to the UICollectionView that contains it. Therefore, if you want to establish a relationship from a cell to a collection view, you need to add a property or ivar to the cell.

 cell = [UICollectionViewCell ...]; cell.collectionView = self.collectionView; 

Secondly, when creating an instance of UICollectionViewCell from nib initWithFrame: is not called; initWithCoder: called instead. You can override initWithCoder: (and call super) or implement -awakeFromNib.

Sometimes what I do, if I need to implement two init methods in one class (e.g. initWithFrame: and initWithCoder :), I have every implementation call one method, called commonInit

 - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self commonInit]; } return self; } - (id)initWithCoder:(NSCoder *)encoder { self = [super initWithCoder:encoder]; if (self) { [self commonInit]; } return self; } - (void)commonInit { // set up your instance } 

This eliminates code duplication and ensures consistent behavior.

Link: UIView Documentation for initWithFrame:

+5
source share

You really shouldn't add a backlink from a cell to CollectionView as an iVar or property, because you end up with a really (really) bad cross reference (objA points to objB and objB points to objA). Besides minor issues such as compilation errors (can be fixed poorly with @class operators), this also leads to serious problems such as objects that cannot be deleted, memory leak, zombies, etc.

Rule of thumb:

parents know about their children, but children should not know about their parents.

In other words: CollectionView knows its cells, but cells should not know their CollectionView.

Possible solutions

  • Recycle your task and your solution . Maybe add a gesture recognizer to the collection, not to the cell. There is -indexPathForItemAtPoint: to provide you with the selected cell.

  • If you absolutely need a backlink: define a protocol and use a delegate . This is a common design pattern in Cocoa / Cocoa Touch. You should read about the delegate design pattern, but in short, this is how you do it:


define the protocol in your cell (remember that the cell does not know about the type of the parent, defining this protocol, it knows for sure that there is one or more methods available in the "parent")

 // in cell.h @protocol MyCellProtocol - (IBAction)doSomething:(id)sender; @end 

add a delegate of type identifier (this means that it can be any object if it conforms to the protocol. In other words: this will be your collectionView, but you do not need to reference it

 // in cell.h @property (assign) id<MyCellProtocol> cellDelegate; 

Now you can call the delegate in your cell:

 // in cell.m, some method: [self.cellDelegate doSomething:nil]; 

finally you need to install a delegate. When you create / customize your cell in the UICollectionViewController, set the controller as a delegate:

 // in collectionViewController.m - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { UICollectionViewCell *cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:@"myCell" forIndexPath:indexPath]; cell.cellDelegate = (id<MyCellProtocol>)self; 
+11
source share

All Articles