I´m trying to implement a CollectionViewController, where the images sizes are shown correctly. But when I implement the method "collectionViewLayout sizeForItemAtIndexPath", none of the images are shown. Does anybody know why? Here is my CollectionViewController code:
#import "PhotosViewController1.h"
#interface PhotosViewController1 ()
#end
#implementation PhotosViewController1
- (void)viewDidLoad
{
[super viewDidLoad];
_carImages = [#[#"Wild-Love.jpg",
#"d919004663f99c934b20c1bd46fcad3e.jpg",
#"164_v-viergalerie.jpg"] mutableCopy];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark -
#pragma mark UICollectionViewDataSource
-(NSInteger)numberOfSectionsInCollectionView:
(UICollectionView *)collectionView
{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section
{
return _carImages.count;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
PhotosCell *myCell = [collectionView
dequeueReusableCellWithReuseIdentifier:#"MyCell"
forIndexPath:indexPath];
UIImage *image;
int row = [indexPath row];
image = [UIImage imageNamed:_carImages[row]];
myCell.imageView.image = image;
return myCell;
}
#pragma mark -
#pragma mark UICollectionViewFlowLayoutDelegate
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
UIImage *image;
int row = [indexPath row];
image = [UIImage imageNamed:_carImages[row]];
return image.size;
}
#end
Related
[update - collection view is nil for some reason...]
None of the collection view delegate methods (cellforitemat, numberofitemsinsection, sizeforitem etc) are being called at all for some reason. I have set the datasource and delegate. I've tried it in interface builder and in code in view did load. Am I missing something??
in the .h:
#interface ViewController : UIViewController<UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout>
#property (nonatomic, strong) NSArray *workoutList;
in the .m (workoutlist.count is 3 on print statement in VDL but not run elsewhere):
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.workoutCV.backgroundColor = [UIColor blackColor];
self.view.backgroundColor = [UIColor blackColor];
self.workoutCV.delegate = self;
self.workoutCV.dataSource = self;
NSLog(#"here %lu", (unsigned long)self.workoutList.count);
}
- (NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section {
NSLog(#"and here %lu", (unsigned long)self.workoutList.count);
return self.workoutList.count;
}
- (nonnull __kindof UICollectionViewCell *)collectionView:(nonnull UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath {
static NSString * const cellId = #"HomeCell";
HomeMenuCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellId forIndexPath:indexPath];
return cell;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(CGRectGetWidth(collectionView.frame), CGRectGetHeight(collectionView.frame) / self.workoutList.count);
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
return 0;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
return 0;
}
I am segue from a different Viewcontroller (HomeController) to get to this new controller. This is the code from the .m of the HomeController:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
ViewController *nextVC = [[ViewController alloc] init];
nextVC.workoutList = #[#"Squats", #"Stiff Leg DL", #"Abs"];
[self.navigationController pushViewController:nextVC animated:true];
}
It pushes the nextVC fine and print statements run but no cells show up and no print statements run from any of the collection view delegate methods
I don't know what happens, but calling reloadData on the collection view causes nothing. Nothing happens. Maybe I'm missing something, I just don't know what.
I've tried with data on launch and it worked, the collection view was populated. But fetching remote data and then calling reloadData afterwards is not populating the collection view.
Thank you in advance
Class is below:
FoodChannelsCollection.h
#import <UIKit/UIKit.h>
#import "YouTubeDataAPI.h"
#interface FoodChannelsCollection: UIViewController <YouTubeDataAPIDelegate, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource>
#end
FoodChannelsCollection.m
#import "FoodChannelsCollection.h"
#import "ChannelCell.h"
#import "UIImageView+ImageLoader.h"
#interface FoodChannelsCollection()
#property (weak, nonatomic) IBOutlet UICollectionView *collectionView;
#end
#implementation FoodChannelsCollection
//#synthesize collectionView;
NSMutableArray *channels;
//-------------------------------------------------------------------------//
// MARK: Controller's main view setup
//-------------------------------------------------------------------------//
- (void)viewDidLoad
{
[super viewDidLoad];
channels = [NSMutableArray new];
YouTubeDataAPI *dataApi = [YouTubeDataAPI getInstance];
dataApi.delegate = self;
[dataApi fetchFirstChannelsBatch];
}
//-------------------------------------------------------------------------//
// MARK: YouTubeDataAPIDelegate
//-------------------------------------------------------------------------//
- (void)getFirstChannelsBatch:(NSArray *)firstChannelsBatch
{
if (firstChannelsBatch == nil) { return; }
NSLog(#"firstChannelsBatch count: %i", [firstChannelsBatch count]);
if ([firstChannelsBatch count] == 0) { return; }
NSLog(#"firstChannelsBatch count(2): %i", [firstChannelsBatch count]);
[channels addObjectsFromArray: firstChannelsBatch];
NSLog(#"Channels count (Del): %i", [channels count]);
[self.collectionView reloadData];
}
//-------------------------------------------------------------------------//
// MARK: UICollectionViewDelegateFlowLayout
//-------------------------------------------------------------------------//
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
int width = [UIScreen mainScreen].bounds.size.width;
return CGSizeMake(width/2, width/2);
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0);
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 0;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
return 0;
}
//-------------------------------------------------------------------------//
// MARK: UICollectionViewDataSource
//-------------------------------------------------------------------------//
- (NSInteger)collectionView:(nonnull UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
NSLog(#"Channels count: %i", [channels count]);
return [channels count];
//return 8;
}
- (nonnull __kindof UICollectionViewCell *)collectionView:(nonnull UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath
{
Channel *channel = channels[indexPath.row];
ChannelCell *cell = (ChannelCell *)[collectionView dequeueReusableCellWithReuseIdentifier: #"ChannelCell" forIndexPath: indexPath];
[cell.thumbnail setImageWithUrl: channel.thumbnailUrl];
[cell.channelTitle setText: channel.channelTitle];
//[cell.channelTitle setText: #"Test Cell"];
return cell;
}
//-------------------------------------------------------------------------//
// MARK: Memory Warning
//-------------------------------------------------------------------------//
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
I am new in objective c. I want to create a layout design like android app store. Which means, i have a tableview and each row of tableview has a collectionview, and one more thing, i am using xcode7 and i want to create a design with storyboard. When i should create a that type of design each tableview row show collectionview but my problem is that each collectionview have save data. but i want to different data in every row. I go throw many tutorial but i can't understand. Can anyone assist me, how to create that type of design? Now i am create a tableview datasourse and delegate method in viewcontroller.m file and also use collection view's datasourse and delegate method into custom tableview cells.m class. please any one assist me
each collectionview have save data. but i want to different data in every row
because your collection view's datasourse and delegate method in tableViewCell is same.maybe it's not ok to determine dataSource and delegate implementation in tableViewCell ,you can delegate it out to your ViewController, and each tableViewCell's has different implementation.
I have try to implementation a demo , it can work ,but i think may have better way. this is my code
Cell.h
//Cell.h
#import <UIKit/UIKit.h>
#class MTTableViewCell;
#protocol MTTableViewCellDelegate <NSObject>
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section InTableViewCell:(MTTableViewCell *)cell;
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:( NSIndexPath *)indexPath InTableViewCell:(MTTableViewCell *)cell;
#end
#interface MTTableViewCell : UITableViewCell<UICollectionViewDelegateFlowLayout,UICollectionViewDataSource>
#property (nonatomic, weak) id<MTTableViewCellDelegate> delegate;
#property (nonatomic, strong) UICollectionView *collectionView;
#property (nonatomic, assign) NSInteger index; // [tablview indexPathForCell:] not work before cell is render
#end
Cell.m
//Cell.m
#import "MTTableViewCell.h"
#interface MTTableViewCell()
#end
#implementation MTTableViewCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
_collectionView = [[UICollectionView alloc] initWithFrame:self.bounds collectionViewLayout:layout];
}
return self;
}
#pragma mark -
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
if (_delegate && [_delegate respondsToSelector:#selector( collectionView:numberOfItemsInSection:InTableViewCell:)]) {
return [_delegate collectionView:collectionView numberOfItemsInSection:section InTableViewCell:self];
}
return 0;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:( NSIndexPath *)indexPath {
if (_delegate && [_delegate respondsToSelector:#selector( collectionView:cellForItemAtIndexPath:InTableViewCell:)]) {
return [_delegate collectionView:collectionView cellForItemAtIndexPath:indexPath InTableViewCell:self];
}
return nil;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *) collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(50, 50);
}
#end
ViewController.m
#import "ViewController.h"
#import "MTTableViewCell.h"
#interface ViewController ()<UITableViewDataSource,UITableViewDelegate,MTTableViewCellDelegate>
#property (nonatomic, strong) UITableView *tableView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.rowHeight = 72.0;
[self.view addSubview:_tableView];
}
#pragma mark - UITableViewDataSource & UITableViewDelegate
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MTTableViewCell *cell = (MTTableViewCell*) [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (!cell) {
cell = [[MTTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
cell.index = indexPath.row;
cell.delegate = self;
[cell.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"CCell"];
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 5;
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:( NSIndexPath *)indexPath {
MTTableViewCell *mtCell = (MTTableViewCell *)cell;
if (!mtCell.collectionView.superview) {
[mtCell addSubview:mtCell.collectionView];
mtCell.collectionView.delegate = mtCell;
mtCell.collectionView.dataSource = mtCell;
}
}
#pragma mark - MTTableViewCellDelegate
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:( NSIndexPath *)indexPath InTableViewCell:(MTTableViewCell *)cell {
UICollectionViewCell *cCell = [collectionView dequeueReusableCellWithReuseIdentifier:#"CCell" forIndexPath:indexPath];
cCell.backgroundColor = [UIColor redColor];
return cCell;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section InTableViewCell:(MTTableViewCell *)cell {
[_tableView indexPathForCell:cell];
return cell.index
;
}
#end
Hope this can help you :)
I have a UIViewController with a UICollectionView on it but Xcode doesn't seem to look like every tutorial I find on the Internet or on YouTube - When I drag a UICollectionViewCell to place in the UICollectionView, it won't let me place it.
Now I'm confused as to how I can link my cell to the UICollectionView.
This is the viewController.h file:
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return [self.imagesArray count];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
ImageViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"imageCell" forIndexPath:indexPath];
NSString *myImageString = [self.imagesArray objectAtIndex:indexPath.row];
cell.imageView.image = [UIImage imageNamed:myImageString];
return cell;
}
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
return CGSizeMake(100.0, 100.0);
}
-(UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
return UIEdgeInsetsMake(5, 5, 5, 5);
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.collectionView.delegate = self;
self.collectionView.dataSource = self;
//[self.collectionView registerClass:[ImageViewCell class] forCellWithReuseIdentifier:#"imageCell"];
self.imagesArray = #[#"shirt1.PNG", #"pants.png", #"pants2.png"];
}
I'm not using a Storyboard interface but individual xib's. When I run this all that appears is the blank black screen. What am I missing?
-registerNib:forCellWithReuseIdentifier:
If you have your cell defined in a NIB, then you register that NIB with the collection view. That is how the collection view know what to load when -dequeueReusableCellWithReuseIdentifier:forIndexPath: is called.
- (void)viewDidLoad
{
// …
UINib nib = [UINib nibWithNibName:#"<the name of your xib>" bundle:nil];
[self.collectionView registerNib:nib forCellWithReuseIdentifier:#"imageCell"];
// …
}
Because you didn't have new a object of UICollectionViewCell in this method:
-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
The "cell" in your method must be set to nil.
I try to add a header to each section of the collectionView.
The collectionView without header works fine. When I checkmark the Accessories Section Header in Interfacebilder, the header will be shown in the simulator.
I added a UICollectionViewFlowLayout Class (as File) and called it within the viewDidLoad of my UICollectionView Controller. In the FlowLayout I want to configure the zIndex and Size.
Now the header will not be shown in the simulator, additionaly I added breakpoints in the UICollectionViewFlowLayout but they will never be hit...
How do I get the headers shown in the collectionview, and how do I influence the zIndex and size of the header in the correct way?
SurroundViewController.h
#import <UIKit/UIKit.h>
#interface SurroundViewController : UICollectionViewController
#end
SurroundViewController.m
#import "SurroundViewController.h"
#import "MagazineCell.h"
#import "LazyJoeHeaderLayout.h"
static NSString * const cellID = #"cellID";
#interface SurroundViewController ()
#end
#implementation SurroundViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.collectionView.collectionViewLayout = [[LazyJoeHeaderLayout alloc] init];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 2;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 30;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
MagazineCell *mCell = (MagazineCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];
mCell.backgroundColor = [UIColor lightGrayColor];
return mCell;
}
#pragma mark Collection view Layout things
// Layout set cell size
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Settings Size for Item at index %d", indexPath.row);
CGSize mElementSize = CGSizeMake(104, 104);
return mElementSize;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
return 2.0;
}
-(CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
return 2.0;
}
// Layout: Set Edgees of whole screen - not mElementsize
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(0, 0, 0, 0);
}
#end
LazyJoeHeaderLayout.h
#import <UIKit/UIKit.h>
#interface LazyJoeHeaderLayout : UICollectionViewFlowLayout
#end
LazyJoeHeaderLayout.m
#import "LazyJoeHeaderLayout.h"
#implementation LazyJoeHeaderLayout
- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes *attributes = [super layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath];
attributes.frame = CGRectMake(0, 0, 100, 100);
attributes.zIndex = 1024;
return attributes;
}
#end
MagazineCell.h and MagazineCell.m not listed as not needed for this problem.
Found a solution to show the header, below the updated code to my question, regarding the headersize.
SurroundViewController
#import "SurroundViewController.h"
#import "MagazineCell.h"
#import "LazyJoe.h"
static NSString * const cellID = #"cellID";
#interface SurroundViewController ()
#property (nonatomic, strong) LazyJoe *lazyJoe;
#end
#implementation SurroundViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.lazyJoe = [[LazyJoe alloc]init];
self.collectionView.collectionViewLayout = self.lazyJoe; // Layout things are in the Flowlayout
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 2;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 30;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
MagazineCell *mCell = (MagazineCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];
mCell.backgroundColor = [UIColor lightGrayColor];
return mCell;
}
LazyJoe.m
#import "LazyJoe.h"
#implementation LazyJoe
- (id)init {
if (!(self = [super init])) return nil;
self.itemSize = CGSizeMake(104, 104);
self.sectionInset = UIEdgeInsetsMake(0,0,0,0); // That the items can align as nearest as possible
self.minimumInteritemSpacing = 2.0f; // spacing between items in one row
self.minimumLineSpacing = 2.0f; // spacing between lines
self.headerReferenceSize = CGSizeMake(self.collectionView.frame.size.width, 140);
return self;
}
#end