UICollectionView not showing cells: - uicollectionview

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;
}

Related

UICollection View - Dont adds new custom cells

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

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.

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.

Custom TableView-Cell (Data from server) select multiple values with accessory change

I am working with TableView and wanted Custom TableViewCell to have a Small Image, Name and one custom image (With Tickmark and without Tick) can be on accessory to show if Cell is selected and if it's not selected it will show without Tick image on unselected cells.
And if i want to select multiple cells then it should show Tick image on selected Cells and Untick image on unselected cells and after that when i click on a button then i should be able to get the selected cell id's.
On the tableView i am getting all the values from the server and images also from URL's but the Tickmark and Unselected Tick mark image will be used the project itself.
So far i have created :
Class .h,.m,.xib of "ResultTableCell" of type UITableViewCell and my Main view "Result" with the TableView and a Button on top (on click of button i'll get the values of selected cells)
ResultTableCell.h
#import <UIKit/UIKit.h>
#interface ResultTableCell : UITableViewCell
#property (nonatomic, retain) IBOutlet UILabel *nameLabel;
#property (nonatomic, retain) IBOutlet UIImageView *thumbImageView;
ResultTableCell.m
#import "ResultTableCell.h"
#implementation ResultTableCell
#synthesize nameLabel,thumbImageView;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
ResultTableCell.xib
The right hand side image on the xib is the place where the accessor image will come.
ResultTableCell.xib
And the main xib
Result.h
#import <UIKit/UIKit.h>
#import "ASIFormDataRequest.h"
#interface Results : UIViewController <UITableViewDelegate,UITableViewDataSource>
{
NSMutableArray *nameData;
}
#property (nonatomic, retain)NSMutableArray *nameData;
#property (nonatomic, retain)NSMutableArray *ImageData;
#property (nonatomic, retain)NSMutableArray *idData;
#property (nonatomic, retain)UITableView *table;
#property (nonatomic, retain) IBOutlet UIButton *done;
#property (nonatomic, retain) NSMutableArray *arFors;
-(IBAction)save_done:(id)sender;
Result.m
#import "Results.h"
#import "ResultTableCell.h"
#interface Results ()
#end
#implementation Results
#synthesize arFors;
#synthesize done,nameData,table,addressData,ImageData,idData;
- (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 from its nib.
self.arFors=[NSMutableArray array];
// I am Getting Name,id and image url data from my HomeViewController
NSLog(#"Name Data from home view is %#",nameData); // 10 Names get's printed in log
NSLog(#"id Data is %#",idData);
NSLog(#"URL image data is %#",ImageData);
table = [[UITableView alloc]initWithFrame:CGRectMake(0, 221, 320, 327) style:UITableViewStylePlain];
table.delegate = self;
table.dataSource = self;
[self.view addSubview:table];
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"Name data count is %d",nameData.count);
return nameData.count;
//return 10;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 70;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
/* UITableViewCell *cell = [tableView dequeueReusableHeaderFooterViewWithIdentifier:#"MainCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MainCell"];
}*/
static NSString *simpleTableIdentifier = #"ResultTableCell";
ResultTableCell *cell = (ResultTableCell *)[table dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ResultTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
if ([self.arFors containsObject:[NSNumber numberWithInt:indexPath.row]]) {
cell.accessoryView = [[ UIImageView alloc ]
initWithImage:[UIImage imageNamed:#"table_tick" ]];
}
else {
cell.accessoryView = [[ UIImageView alloc ]
initWithImage:[UIImage imageNamed:#"table_add" ]];
}
NSLog(#"data is ************* %#",nameData);
cell.nameLabel.text = [nameData objectAtIndex:indexPath.row];
NSURL * imageURL = [NSURL URLWithString:[ImageData objectAtIndex:indexPath.row]];
NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage * image2 = [UIImage imageWithData:imageData];
cell.ImageView.image = image2;
cell.ImageView.contentMode = UIViewContentModeScaleAspectFit;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"didSelectRowAtIndexPath %d",indexPath.row);
if ([self.arFors containsObject:[NSNumber numberWithInt:indexPath.row]]) {
[self.arFors removeObject:[NSNumber numberWithInt:indexPath.row]];
}
else{
[self.arFors addObject:[NSNumber numberWithInt:indexPath.row]];
// [self.table cellForRowAtIndexPath:indexPath];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[tableView reloadData];
}
-(IBAction)save_done:(id)sender
{
NSLog(#"selected cell values are %#",self.arFors);
}
Now with this code everything is working fine (tick image is shown on selected cells and untick image on unslected cells and on clicking the Done button i am getting the selected cell values),
But the Problem comes when i tapp on a cell then it like hangs and takes 5-6 seconds of time to change accessor image as it fires [tableView reloadData] in didselectrowatindexpath method so all data reloads again in the tableview and then the accessor image changes, please can any one correct my code or enhance it so that it works fast.
I have tried a lot of ways but i was not able to do it without the reloading of table and if i reload table it takes long time.
Coding help will be much tankful.
Your problem is:
NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
Because it downloads all of the image data from the network each time you reload the table view. You should be doing this asynchronously and caching the returned image so you don't need to download it repeatedly. Take a look at a library like SDWebImage to help you with this.

Adding UITableView to existing UIViewController

I have a UIViewController which open up a Camera, after doing the imagePickerController:didFinishPickingMediaWithInfo: a UITableView shall be shown.
Somehow the tableView delegation code is not triggered. A tableView is shown on my iPhone but with empty rows. Seems that just the IB Stuff is displayed without the code. But I cannot figure out what I missed.
How do I get the UITableView working?
MainStoryboard.storyboard
Camera View Controller Scene
----------------------------
Camera View Controller
View
Image View // hooked up with .h
Table View // hooked up with .h
Table View Cell - clocation
CameraViewController.h
#import <UIKit/UIKit.h>
#interface CameraViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate, UITableViewDataSource, UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UIImageView *imageView; // hooked up with IB UIImageView
#property (strong, nonatomic) NSMutableArray *locations;
#property (strong, nonatomic) IBOutlet UITableView *tableView; // hooked up with IB UITableView
#end
CameraViewController.m (Updated 20130725 with working solution)
#import "CameraViewController.h"
#interface CameraViewController ()
#end
#implementation CameraViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// self.locations = [[NSMutableArray alloc] init];
// is filled with content when photo is taken. Means has content when tableview shall be shown.
self.locations = #[ #"foo", #"bar" ]; // dummy setup for this thread
// Do any additional setup after loading the view.
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
// select Photo
} else {
[self takePhoto];
}
[self initTableView];
}
// [...] Camera Stuff
#pragma mark - table view things
-(void)initTableView {
_tableView.dataSource = self;
_tableView.delegate = self;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.locations.count; // a breakpoint is configured but never get hit...
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"clocation";
// Not working in this case:
// UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// You have to use this one:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [NSString stringWithFormat:#"Empty Cell %d", indexPath.row];
return cell;
}