Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS

How to assign a ViewController as a "delegate" and "datasource" for a CollectionView in itself?

Hi,

I want to use a CollectionView inside my main ViewController instead of a CollectionViewController.

Step 1: Give the delegation and data sourcing duty of this CollectionView to my main ViewController.

Step 2: In implementation file of this ViewController, specify section and item counts and the cell id to reuse.

Step 3: Fill ind the cells.


Is this completely a wrong approach to use CollectionViews?

If not, i really need your leading ideas to manage this. Like where to declare/implement what?

Many thanks indeed.

you should be able to do this (and should need to if you want to do anything with your collectionviewcontroller) in your header (.h) file do this: @interface YourViewController : YourSubClass <UICollectionViewControllerDelegate, UICollectionViewControllerDataSource> if you cmd+click on either one, you can see the methods you can override in your viewcontroller's implementaion (.m) file. you'll need some of these to add and edit cells. hope this answered your question.

Hi Whitney.

For your suggestion i think i will need to have two interfaces in one .h file. Like:

#import <UIKit/UIKit.h>

@interface HomeViewController : UIViewController

@property (weak, nonatomic) ..........

@end

@interface HomeViewController2 : UICollectionViewController

.........

@end

And also two @implementation's in .m file.

Because i have to satisfy "a CollectionView, five views, three ImageViews and four Labels" in one scene. Please, correct me if i'm wrong.

I'll give it a try, thank you.

I don't know if having two interfaces and two implementations would be the best way. Of course, I've never tried it so it may work but you could also create a separate custom collectionviewcontroller and make your homeviewcontroller a delegate.

" ... make your homeviewcontroller a delegate" What exactly do you mean by this?

By the way, i tried both:

  1. create a custom controller file (subclass of UICollectionViewController)
  2. use two interfaces and implementations in HomeVİewController

These two gives no error until i drag outlet + signs from Show the Connections inspector tab of my CollectionView to its superview; which is in my HomeViewController scene.

In both cases result is 'NSInvalidArgumentException', reason: '-[HomeViewController collectionView:numberOfItemsInSection:]: unrecognized selector sent to instance 0x7c151770'

Can the actual problem be at telling Xcode or my CollectionView, who is responsible for its delegate and datasource?

like this

CustomCollectionViewController.h

#import <UIKit/UIKit.h>

@protocol CustomCollectionViewControllerDelegate

@interface CustomCollectionViewController : UICollectionViewController

// properties and methods @property (weak, nonatomic) id"side carrot"CustomViewControllerDelegate"side carrot" delegate;

@end

@protocol CustomCollectionViewControllerDelegate

// delegate method example below

- (void)someMethod;

@end


HomeViewController.h

#import <UIKit/UIKit.h>

#import "CustomCollectionViewController.h"

@interface HomeViewController : UIViewController "side carrot"CustomCollectionViewControllerDelegate"side carrot"

// properties and methods

@property (weak, nonatomic) IBOutlet CustomCollectionViewController *collectionView;

@end


HomeViewController.m

@implementation HomeViewController

- (void)viewDidLoad {

self.collectionView.delegate = self;

}

- (void)someMethod {

// do something

}

sorry i didnt realize that my first comment didn't register the sideways carrots but it should have been @interface YourViewController : YourSubClass "side carrot"UICollectionViewDelegate, UICollectionViewDataSource"side carrot"

1 Answer

We got it!

Here is how you use a CollectionVİew in a ViewController (as delegate/datasource) rather than a CollectionViewController, for everyone in need:

Just HomeViewController file (.h and .m) is enough. No need to any custom CollectionVİewController file.

In your HomeViewController.h file update your @interface to:

@interface HomeViewController : UIViewController < UICollectionViewDelegate, UICollectionViewDataSource >

Drag a CollectionView into your ViewController.

Ktrl+drag CollectionView into your HomeViewController.h @interface section to have this line of code:

@property (strong, nonatomic) IBOutlet UICollectionView *yourCollectionView;

While your CollectionVİew selected in the storyboard go to Connections inspector tab an drag both delegate and datasource Outlets onto your ViewController in the Document Outline section

While the only cell in your CollectionView is selected go to Attributes Inspector and write myCell into Identifier field.

In HomeVİewController.m file add these lines:

@implementation HomeViewController
...
...
...
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return 20;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"myCell" forIndexPath:indexPath];

    cell.backgroundColor = [UIColor lightGrayColor];

    return cell;
}

@end

Finally, fill your CollectionVİew background with white so that you can see your CollectionViewCells like below:

- (void)viewDidLoad {
...
    self.yourCollectionView.backgroundColor = [UIColor whiteColor];
...
} 

Many thanks to Whitney.