UICollection View - Dont adds new custom cells - objective-c

I have a collectionView inside a view. I did setup hte datasource, the delegate and everything.
This cell is working:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [self.collectionAddedMembers dequeueReusableCellWithReuseIdentifier:cellReuseIdentifierAdded forIndexPath:indexPath];
cell.backgroundColor = [colores objectAtIndex:arc4random_uniform(6)];
return cell;
}
But on my custom cell AddedMemberCollectionViewCell it dont adds new cells:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
AddedMemberCollectionViewCell *cell = [self.collectionAddedMembers dequeueReusableCellWithReuseIdentifier:cellReuseIdentifierAdded forIndexPath:indexPath];
NSArray *firstSection = [selectedMembersData objectAtIndex:0];
SelectedContacto *cellData = [firstSection objectAtIndex:indexPath.row];
NSMutableDictionary *dataForConfigure = [[NSMutableDictionary alloc] init];
[dataForConfigure setObject:cellData.contactAvatar forKey:#"contactAvatar"];
[dataForConfigure setObject:cellData.contactName forKey:#"contactName"];
[dataForConfigure setObject:cellData.memberId forKey:#"contactName"];
[cell configure:dataForConfigure];
return cell;
}
This is the code of the custom cell.
.h file:
#interface AddedMemberCollectionViewCell : UICollectionViewCell
#property (nonatomic) IBOutlet UIImageView *avatar;
#property (nonatomic) IBOutlet UILabel *memberName;
#property (nonatomic) IBOutlet UIButton *removeMember;
#property (nonatomic) NSNumber *memberId;
- (void) configure:(NSDictionary*)cellData;
#end
.m file
#import "AddedMemberCollectionViewCell.h"
#implementation AddedMemberCollectionViewCell
- (void) configure:(NSDictionary*)cellData {
self.avatar = [cellData objectForKey:#"contactAvatar"];
self.memberName = [cellData objectForKey:#"contactName"];
self.memberId = [cellData objectForKey:#"memberId"];
}
#end
I could provide more code, but I am thinking would not be necessary. What is happening here?
EDIT:
Registering in viewDidLoad:
self.searchBar.delegate = self;
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.collectionAddedMembers.dataSource = self;
self.collectionAddedMembers.delegate = self;
[self.collectionAddedMembers registerClass:AddedMemberCollectionViewCell.class forCellWithReuseIdentifier:cellReuseIdentifierAdded];

Are you sure that the cell is not actually added to your collection view?
However, you were not doing it right, as calling dequeueReusableCellWithReuseIdentifier will NOT create UICollectionViewCell but re-use an existing cell, hence your initialization code in init will never have chance to be called.
A good approach should look like this:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
CustomCell *cell = (CustomCell *)[collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
NSDictionary *cellData = [data objectAtIndex:indexPath.row];
// Call custom cell's configure function to init cell content
[cell configure:cellData];
return cell;
}
#interface CustomCell : UICollectionViewCell
-(void)configure:(NSDictionary *)data;
#end
#implementation CustomCell
-(void)configure:(NSDictionary *)data {
// Init your cell content
}
#end

Related

Custom Collectionview under each tableview rows

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 :)

CollectionViewController not seeing properties on the DetailViewController

I'm a novice and I'm trying to understand why my CollectionViewController is not seeing properties on the DetailViewController...any tips or insight would be appreciated. Code below...for my detailViewController.h and also my CollectionViewController.m, respectively.
// DetailViewController.h
// RecipePhoto
//
#import <UIKit/UIKit.h>
#interface DetailViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIImageView *recipeImageView;
#property (nonatomic) NSString *recipeImageName;
- (IBAction)close:(id)sender;
#end
#import "RecipeCollectionViewController.h"
#import "DetailViewController.h".
#interface RecipeCollectionViewController () <UICollectionViewDataSource, UICollectionViewDelegate>
{
NSArray *recipeImages;
}
#end
#implementation RecipeCollectionViewController
static NSString * const reuseIdentifier = #"Cell";
- (void)viewDidLoad {
[super viewDidLoad];
recipeImages = [NSArray arrayWithObjects:#"angry_birds_cake.jpg", #"creme_brelee.jpg", #"egg_benedict.jpg", #"full_breakfast.jpg", #"green_tea.jpg", #"ham_and_cheese_panini.jpg", #"ham_and_egg_sandwich.jpg", #"hamburger.jpg", #"instant_noodle_with_egg.jpg", #"japanese_noodle_with_pork.jpg", #"mushroom_risotto.jpg", #"noodle_with_bbq_pork.jpg", #"starbucks_coffee.jpg", #"thai_shrimp_cake.jpg", #"vegetable_curry.jpg", #"white_chocolate_donut.jpg", nil];
}
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showRecipePhoto"]) {
NSArray *indexPaths = [self.collectionView indexPathsForSelectedItems];
// Get the new view controller using [segue destinationViewController].
DetailViewController *detailViewController = [segue destinationViewController];
NSIndexPath *indexPath = [indexPaths objectAtIndex:0];
// Pass the selected object to the new view controller.
DetailViewController.recipeImageName = [recipeImages[indexPath.section] objectAtIndex:indexPath.row];
[self.collectionView deselectItemAtIndexPath:indexPath animated:NO];
}
}
#pragma mark <UICollectionViewDataSource>
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
//return arrayName.count;
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return recipeImages.count;
}
//provides the data for the collection view cells
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
// Configure the cell
UIImageView *recipeImageView = (UIImageView *)[cell viewWithTag:100];
recipeImageView.image = [UIImage imageNamed:[recipeImages objectAtIndex:indexPath.row]];
return cell;
}
You are trying to use recipeImageName as a class property in prepareForSegue:
DetailViewController.recipeImageName = [recipeImages[indexPath.section] objectAtIndex:indexPath.row];
should be
detailViewController.recipeImageName = [recipeImages[indexPath.section] objectAtIndex:indexPath.row];
Pay close attention to the capitalisation of the first letter. DetailViewController is the class; detailViewController is the local variable.

Setting cell in UICollectionView

I am attempting to set an imageView in a cell in a UICollectionview. No images ever appear. I am also tried to set a label but have had no luck
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
photoCollectionViewCell *photoCell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
// Configure the cell
NSURL *url = [NSURL URLWithString:self.imageURLArray[indexPath.row]];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
UIImage *tmpImage = [[UIImage alloc] initWithData:data];
//photoCell.photoImageView.image = tmpImage;
photoCell.photoLabel.text = #"l";
return photoCell;
}
One thing I did notice is that "photoCell" always returns null.
I am registering my collectionview like this:
[self.collectionView registerClass:[photoCollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier];
My cell interface header file is:
#interface photoCollectionViewCell : UICollectionViewCell
#property (weak, nonatomic) IBOutlet UIImageView *photoImageView;
#property (weak, nonatomic) IBOutlet UILabel *photoLabel;
#end
My first guess would be to return an instance of photoCollectionViewCell instead of the default UICollectionViewCell:
- (photoCollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
}
Second guess:
Where do you set your "reuseIdentifier" variable and what value is assigned to it? You can set a reuseIdentifier as follows:
static NSString *CellIdentifier = #"MyCustomCell";
and then set it to your:
[self.collectionView registerClass:[photoCollectionViewCell class] CellIdentifier];
and:
photoCollectionViewCell *photoCell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
and register your ReuseIdentifier on your storyboard custom cell:

How detect indexPath on click button at row?

I have this UItableView:
I would like to increment/decrement the concrete UIProgressView at row, when I clicked on minus/plus and than also reload, whole UITableView, because all rows are interdependent. I don't how detect on which row was pressed the minus/plus UIButton. I tried to use rowDidSelect, but it didn't work. Could you please advise me please?
EDITED
I have a class for UITableCell (ActivityCell - class) and class for UITableViewController (lessonActivityTVC - class). At class of Cell I have IBOutlets.
ActivityCell.h
#interface ActivityCell : UITableViewCell
#property (strong, nonatomic) IBOutlet UILabel *studentNameLabel;
#property (strong, nonatomic) IBOutlet UIProgressView *progressView;
In ActivityCell.m I have nothing new. I had here a IBActions for buttons, but I moved the actions into lessonActivity.m because, when I press any button I need reload the UITableView and I didnt know how do it in ActivityCell.m. My code of lessonActivityTVC.m is here:
#implementation tchLessonActivityTVC
#define debug 1
- (IBAction)incrementActivity:(id)sender {
NSLog(#"increment");
}
- (IBAction)decrementActivity:(id)sender {
NSLog(#"decrement");
}
-(void)fetchData{
CoreDataHelper *cdh = [(AppDelegate*)[[UIApplication sharedApplication]delegate]cdh];
SchoolClass *schoolClass = (SchoolClass*)[cdh.context existingObjectWithID:[IDsManager getClassID] error:nil];
Lesson *lesson = (Lesson*)[cdh.context existingObjectWithID:[IDsManager getLessonID] error:nil];
if (lesson.activities.count == 0) {
for (Student *student in schoolClass.students) {
Activity *activity = [NSEntityDescription insertNewObjectForEntityForName:#"Activity" inManagedObjectContext:cdh.context];
activity.student = student;
activity.lesson = lesson;
[lesson addActivitiesObject:activity];
[student addActivitiesObject:activity];
}
}
self.activities = [NSArray arrayWithArray:[lesson.activities allObjects]];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.delegate = self;
[self fetchData];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.activities.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(debug == 1){
NSLog(#"Running %# '%#'",self.class, NSStringFromSelector(_cmd));
}
static NSString *cellIndetifier = #"Activity Cell";
ActivityCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIndetifier
forIndexPath:indexPath];
Activity *activity = [self.activities objectAtIndex:indexPath.row];
cell.studentNameLabel.text = activity.student.name;
CGAffineTransform transform = CGAffineTransformMakeScale(1.0f, 5.0f);
cell.progressView.transform = transform;
cell.progressView.progress = 0.32f;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"selected index is %d",indexPath.row);
}
#end
UITableView has a delegate method didSelectRowAtIndexPath: and you get the indexPath.row from there. Don't forget to set your class as a UITableViewDelegate by adding <UITableViewDelegate> on the end of #interface line and setting
tableView.delegate = self;
in code, or do it in Interface Builder. If you are on UITableViewController, you get this for free.
Edit:
Here is the delegate pattern example:
tableviewcell h
#protocol TableViewCellDelegate <NSObject>
- (void)requestToReloadTableViewFromCell:(UITableViewCell *)cell;
#end
#interface TableViewCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UILabel *dateLabel;
#property (weak, nonatomic) id <TableViewCellDelegate> cellDelegate;
#end
tableviewcell m
- (IBAction)buttonAction:(UIButton *)sender
{
[self.cellDelegate requestToReloadTableViewFromCell:self];
}
tableviewcontroller m
#interface TableViewController () <TableViewCellDelegate>
#end
#implementation TableViewController
- (void)requestToReloadTableViewFromCell:(UITableViewCell *)cell
{
NSLog(#"%d", [[self.tableView indexPathForCell:cell] row]);
[self.tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
// Configure the cell...
cell.cellDelegate = self;
cell.dateLabel.text = [[NSDate date] description];
return cell;
}
you can use the tag with these buttons programatically in cellForRowAtIndexPath method. Tag should be different for each button (you can use some formula, for example tag will be equal to row no). in this way when button will be pressed you will check tag first and can know which button is pressed at which row.

UICollectionView not showing cells:

I am trying to use UICollectionView to show the first 10 photos from my facebook profile. However, whenever I run the app, the UICollectionView does not show anything - it remains black and I dont see any cells. (I have set the background colour of the cells to blue and colour of the CollectionView to black, but I dont even see the blue cells)
I am using SDWebImage to load photos onto the cells.
Thank you in advance for any help
Here is my code:
In my header file -
#import <UIKit/UIKit.h>
#import <FacebookSDK/FacebookSDK.h>
#interface LNViewController : UIViewController <FBFriendPickerDelegate,UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
#end
In my .m file -
#import "LNViewController.h"
#import <SDWebImage/UIImageView+WebCache.h>
#property (weak, nonatomic) IBOutlet UICollectionView *photoCollectionView;
- (void)viewDidLoad
{
[super viewDidLoad];
[self refreshArray];
//fetch photos from facebook (this function also has [self.photoCollectionView reloadData] in it;
[self fetchPhotosMe];
[self.photoCollectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"photoCell"];
[self.photoCollectionView reloadData];
}
#pragma Mark UICollectionView
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 10;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"photoCell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
//create array with URLs
NSMutableArray *photosURL = [[NSMutableArray alloc] init];
for (int i = 0; i <10; i++){
NSDictionary *photoDic = [self.photosMeArray objectAtIndex:i];
[photosURL addObject:[photoDic valueForKey:#"src"]];
}
//Load Cells
UIImageView *photoImageView = (UIImageView *)[cell viewWithTag:100];
[photoImageView setImageWithURL:[NSURL URLWithString:[photosURL objectAtIndex:indexPath.row]]];
return cell;
}