xcode Converting UITableView to UICollectionView (no valid cell) - xcode

EDIT: I should specify that this only happens when I attempt to use the UICollectionViewFlowLayout, not when I try to use a custom view. But either way nothing ever shows up on the CollectionView though it was working just fine before I converted from a TableView.)
So I've been trying to convert a UITableView that I had into a UICollectionView. So far so good. But when I try to run the app it gives me the error:
'the collection view's data source did not return a valid cell from -collectionView:cellForItemAtIndexPath: for index path {length = 2, path = 0 - 0}'
I checked all the similar questions and answers here... so in my viewDidLoad I have (tableView is actually a UICollectionView):
UINib * placeCell = [UINib nibWithNibName:#"Shops" bundle:nil];
[self.tableView registerNib:placeCell
forCellWithReuseIdentifier:CellIdentifier];
#pragma mark - UICollectionViewDataSource
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UICollectionView *)tableView numberOfItemsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [_entries count];
//return 5;
}
- (void)tableView:(UICollectionView *)tableView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.item == [_entries count]-1 && page > 1) {
NSLog(#"load more");
//add footer view loading
if (c_page == page) {
// _tableView.tableFooterView = nil;
}
else
{
c_page++;
[self loadPlace:c_page];
}
}
}
- (UICollectionViewCell *)tableView:(UICollectionView *)tableView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
PlaceCell *cell = (PlaceCell *)[tableView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
UINib * placeCell = [UINib nibWithNibName:#"Shops" bundle:nil];
//cell = [cellLoader instantiateWithOwner:self options:nil];
NSArray *topLevelItems = [placeCell instantiateWithOwner:self options:nil];
cell = [topLevelItems objectAtIndex:0];
Place *p = [_entries objectAtIndex:indexPath.row];
cell.placeName.text = p.PName;
NSLog (#"p:%#", p.PName")
cell.placeImg.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:p.PImage]]];
return cell;
}
I went into the xib of the UICollectionViewCell (PlaceCell) and made sure that "Cell" was the reuseidentifier. And I made sure that the datasource and delegate were connected to file's owner in the collectionView.
I also noticed that when I use a custom layout instead of the flow layout (like this one: https://github.com/ShadoFlameX/PhotoCollectionView/blob/master/CollectionViewTutorial/BHPhotoAlbumLayout.m ) it doesn't give me that error... but my collectionview still isn't populated.
So I'm wondering if there's some sort of log I can run or something I can do to figure out what's going wrong. Because I've tried all the solutions I've seen and it hasn't gotten me anywhere.

When you make a cell in a xib file you should register the xib, not the class. Also, when you register either the class or xib (or make the cell in the storyboard), you don't need an if (cell==nil) clause because your cell will never be nil when you dequeue it with dequeueReusableCellWithReuseIdentifier:forIndexPath:. You should delete that clause.

So the problem is: "Switched from UITableView to UICollectionView and no valid cell is being returned." It is really a two part answer. The crux of which is every instance of UITableView...
_tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 50, self.view.bounds.size.width, self.view.bounds.size.height-50)];
...you want to turn into "CollectionView"
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 50, self.view.bounds.size.width, self.view.bounds.size.height-50)];
Everything that's a "row":
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
...you'll want to turn into an "item."
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
Ultimately I had to delete the following section entirely:
UINib * placeCell = [UINib nibWithNibName:#"Shops" bundle:nil];
//cell = [cellLoader instantiateWithOwner:self options:nil];
NSArray *topLevelItems = [placeCell instantiateWithOwner:self options:nil];
cell = [topLevelItems objectAtIndex:0];
My best guess is that the Nib was being loaded twice and that Xcode was complaining that the data wasn't being loaded by the original. So getting rid of that second entry got my cells loaded and populated with data. Hope this helps someone.

Related

Switched from tableview to colelctionview now didselectitematindexpath not called

So I switched from a UITableView to a UICollectionView. The cells are all loading just fine and look beautiful, but now I can no longer select any of them. The taps are recognized in the logs, but it doesn't take me to the view that it's supposed to take me to anymore.
The only things that changed really are the ones the ones you see commented out in the "cellForItem" section. Everything else is identical to how it was when it was working in the TableView. It's just supposed to take me to the ViewController specified when you tap. Instead the tap is recorded, but it does nothing. Any help would be appreciated.
Also I tried getting rid of the [collectionView deselectItemAtIndexPath:indexPath animated:YES];
...but it didn't make any difference.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
PlaceCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
// Configure the cell
//UINib * placeCell = [UINib nibWithNibName:#"Shops" bundle:nil];
// NSArray *topLevelItems = [placeCell instantiateWithOwner:self options:nil];
// cell = [topLevelItems objectAtIndex:0];
Place *p = [_entries objectAtIndex:indexPath.row];
cell.placeName.text = p.PName;
NSLog(#"p:%#",p.PName);
cell.placeName.textColor = [UIColor colorWithRed:3/255.0f green:6/255.0f blue:4/255.0f alpha:1.0f];
NSString *pIcon;
pIcon = typeName;
//NSLog(pIcon);
cell.placeImg.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:p.PImage]]];
NSLog(#"i:%#",p.PImage);
return cell;
}
-(void) collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"Tap Recognized");
[collectionView deselectItemAtIndexPath:indexPath animated:YES];
Place *p = [_entries objectAtIndex:indexPath.row];
DetailPlaceViewController * pvc = [[DetailPlaceViewController alloc] init];
[pvc setPlace:p];
[self.navigationController pushViewController:pvc animated:YES];
}
Well this one was fun...
For some odd reason my navigation controller isn't working... so of course using the navigation controller to load a view wasn't going to work. Simple enough solution... load the view without the navigation controller. I was just going to delete this question, but maybe somebody might be in a similar situation one day:
[self presentViewController:pvc animated:YES completion:nil];

UIImage doesn't show unless i click on my table cell

I've spent some time writing an xcode application today. I'm using a UITableView with a seperate xib for the table view cell. All is working well besides one quirky thing. In my code I set my image on the table cell xib from an array. When i run the app I've found out that the image does not appear on the table cell until I click on the table cell. And when I click on a different cell, the image on my previously selected cell disappears.
Funny thing is that I set my label on the table cell xib exactly the same way however I don't get the issue with the label.
Here is my code. I would greatly appreciate some help.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = nil;
cell = [tbHealthCheck dequeueReusableCellWithIdentifier:#"CONTENT"]; //all the cells in this table are named content (identifier for all cells in table)
if (cell == nil){
[[NSBundle mainBundle] loadNibNamed:#"FirstViewTableCell" owner:self options:nil];
cell = tcHealthCheck;
tcHealthCheck = nil;
}
UILabel *l1 = (UILabel *) [cell viewWithTag:0];
[l1 setText:[healthCheckCategory objectAtIndex:indexPath.row]];
l1.font = [UIFont fontWithName:#"arial" size:14];
[l1 setTextColor:[UIColor blackColor]];
UIImageView *img1 = (UIImageView *) [cell viewWithTag:1];
NSString *status = [healthCheckStatus objectAtIndex:indexPath.row];
if ([status isEqualToString:#"RED"])
{
img1.image = [UIImage imageNamed:#"red-light-badge.png"];
}
else if ([status isEqualToString:#"YELLOW"])
{
img1.image = [UIImage imageNamed:#"yellow-light-badge.png"];
}
else if ([status isEqualToString:#"GREEN"])
{
img1.image = [UIImage imageNamed:#"green-light-badge.png"];
}
return cell;
}

Xcode didSelectRowAtIndexPath on tableview not called

I have been looking until 6 o'clock this morning, but I can't figure out why the didSelectRowAtIndexPath method is not being called. I am getting quite desparate on this one.
The tableview is shown properly, but I cannot succeed to enable the selection of a cell.
In the header file , I added:
#interface AlertsTable : UIViewController<UITableViewDelegate, UITableViewDataSource, CMPopTipViewDelegate>{
UITableView *TableView;
}
#property (nonatomic, retain) UITableView *TableView;
In the implementation file:
#synthesize TableView;
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
//Set the title
//Format Alerts table
//self.view.backgroundColor = [UIColor redColor];
CGFloat sideMargin = 10;
CGFloat topBottomMargin = 44;
CGFloat originX = sideMargin;
// compute width based on view size
CGFloat sizeWidth = (self.view.bounds.size.width - (sideMargin * 2));
CGFloat originY = topBottomMargin;
// compute height based on view size
CGFloat sizeHeight = (self.view.bounds.size.height - (topBottomMargin * 2));
//self.view.frame = CGRectMake(originX, originY, sizeWidth, sizeHeight);
self.TableView = [[UITableView alloc] initWithFrame:CGRectMake(originX, originY, sizeWidth, sizeHeight) style:UITableViewStylePlain];
//Initialize the array.
AlertsItems = [[NSMutableArray alloc] initWithObjects: #"Alert 1", #"Alert 2", #"Alert 3" , #"Alert 4", #"Alert 5", #"Alert 6", nil];
[self.TableView setDelegate:self];
[self.TableView setDataSource:self];
[self.view addSubview:TableView];
TableView.userInteractionEnabled = YES;
TableView.allowsSelection = YES;
TableView.allowsSelectionDuringEditing = YES;
NSLog(#"delegate:%# dataSource:%#", self.TableView.delegate, self.TableView.dataSource);
}
The delegate and datasource are both not nil on the check.
Note that the "Alertstable" inherits from a UIViewController, not a UITableViewController.
This is necessary due to the implementation I chose: the tableview is shown on a popupwindow shown on the screen (using another class that I took from the internet).
This is the didSelectRowAtIndexPath method:
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *alertString = [NSString stringWithFormat:#"Clicked on row #%d", [indexPath row]];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:alertString message:#"" delegate:self cancelButtonTitle:#"Done" otherButtonTitles:nil];
[alert show];
}
The methods:
[super touchesBegan:...];
[super touchesEnded:...];
[super touchesMoved:...];
are not implemented.
I added the AlertTable from another ViewController
AlertsTable *AlertTable = [[AlertsTable alloc] WithButton:sender withArray:self.PopTipViews];
[self.view addSubview:AlertTable.view];
I also implemented:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Set up the cell...
[[cell textLabel] setText:[AlertsItems objectAtIndex:indexPath.row]];
NSLog (#"%#",[AlertsItems objectAtIndex:indexPath.row]);
return cell;
}
Do you have any idea what the problem could be?
I'm not very experienced in Xcode and I'm really stuck.
Edit:
I know that it is not custom, but the link to the project can be found here (perhaps I'm overlooking something:
https://www.bilbu.be/BarConnect_v2.zip
The LoginViewController.xib is not properly linked (it is available in the en.lproj subfolder) so you may need to link first (I noticed too late and I had the file uploaded by a friend before - I cannot re-upload it myself unfortunately).
ViewController VC class calls the AlertsTable VC class. There is more in the project that I suppose you can ignore...
Note that the purpose of this project is only to serve as visual interface prototype. It is not meant to be the best optimized application (this is what other developers will do). If this doesn't work, I will use Photoshop to create the interfaces, but I guess that's not gonna be as convincing...
I successfully compiled your project. The problem is that you're going against the MVC pattern. The controller (AlertsTable) is inside of a view (CMPopTipView). I'd suggest you to rethink the hierarchy of the controllers and views. Hope this will help you.
Try changing
TableView.userInteractionEnabled = YES;
TableView.allowsSelection = YES;
TableView.allowsSelectionDuringEditing = YES;
to
self.TableView.userInteractionEnabled = YES;
self.TableView.allowsSelection = YES;
self.TableView.allowsSelectionDuringEditing = YES;
and are you allocating self.TableView? Something like...
self.TableView = [[UITableView alloc] init];//[[UITableView alloc] initWithStyle:UITableViewStylePlain];

How to update detailView using a popover

I have a TableViewController which is represented by a popover, that is displayed by selecting a bar button item on a tool bar. I'm having a problem however that when I select an item from the table in the popover it doesn't update the view (affirmaPDFViewController)
Here is the DidSelectRowAtIndex method for my PDFTableController (the popover):
- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
affirmaPDFViewController.detailItem = [NSString stringWithFormat:#"%#", [listOfPDF objectAtIndex:indexPath.row]];
affirmaPDFViewController.i = indexPath.row;
NSLog(#"%d", indexPath.row);
NSLog(#"%#", [listOfPDF objectAtIndex:indexPath.row]);
NSLog(#"%d", affirmaPDFViewController.i);
NSLog(#"%#", affirmaPDFViewController.detailItem);
}
Here the indexPath.row and the objectAtIndex:indexPath.row all return the correct values. However when I assign the variables from affirmaPDFViewController to those values they just return 0 and null.
I've been told it is because I haven't created an instance of affirmaPDFViewController. However, I'm not sure how to create such an instance. What code would I put in this method to get this to work?
Thanks in advance!
- (void)viewDidLoad
{
[super viewDidLoad];
affirmaPDFViewController = [[NameOfClassGoesHere alloc] initWithNibName:#"NibNameGoesHere" bundle:nil];
}

Issue with UITableView - updating table values

I am a newbie. I have written some code for UITable but I am unable to update table values after adding the values to the array. I'm using a tableview subclass. The code is as follows. Check the last function. Now how can I update my table values?
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
//#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//#warning Incomplete method implementation.
// Return the number of rows in the section.
return [_phones count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
HLPFoundPhones *p = (HLPFoundPhones *)[_phones objectAtIndex:indexPath.row];
NSString *subtitle = [NSString stringWithFormat:#"Found (%1.2f,%1.2f) on %#" ,[p loc].x, [p loc].y , [p foundDate]];
cell.textLabel.text = [p name];
cell.detailTextLabel.text = subtitle;
return cell;
}
- (void)insertNewObject
{
HLPPhonesAdd *view = [[HLPPhonesAdd alloc]initWithNibName:#"HLPPhonesAdd" bundle:nil];
[self.navigationController pushViewController:view animated:YES];
[view release];
}
- (void)updateTable:(CGPoint)loc name:(NSString *)_name{
HLPFoundPhones *a = [[HLPFoundPhones alloc]initWithLoc:loc name:_name];
[_phones addObject:a];
[phones reloadData];
}
call
[yourTableView reloadData];
in your updateTable Function..
- (void)updateTable:(CGPoint)loc name:(NSString *)_name{
HLPFoundPhones *a = [[HLPFoundPhones alloc]initWithLoc:loc name:_name];
[_phones addObject:a];
//give your tableView object instead of yourTableView
[yourTableView reloadData];
}
check value of _phone count and use in function
- (void)updateTable:(CGPoint)loc name:(NSString *)_name
{
HLPFoundPhones *a = [[HLPFoundPhones alloc]initWithLoc:loc name:_name];
[_phones addObject:a];
[table_name reloaddata];
}
Confirm the array _phones is allocated.
Then there will be problems if the [tableview reloadData] is called inside a thread.
So confirm the reloadData is called from the main thread.
First of all, your cell identifier looks to be same for all cells, which may confuse iOS which cell needs to be dequeued. So, keep your cell identifiers unique, something like below :
NSString *cellIdentifier = [NSString stringWithFormat:#"Cell-%d", indexPath.row];
then, after table view is first displayed, update your datasource and call:
[tableView reloadData];

Resources