I am trying to build an application, that uses reusable UITableViewCells. In my 1st UITableView everything worked right, but now, in my 2nd table I can't use the reusable UITableViewCell, the Cell just stays blank. Here are my configurations:
1; I created a UITableViewCell class
2; I linked the UITableViewCell to the costume UITableViewClass I created in step one
3; I set the "Reuse identifier" to Cell1
4; I added some content to the reusable UITableViewCell
5; I imported the costume UITableViewCell class to my UIViewController
6; I added the standard UITableView code to my UIViewController: <UITableViewDataSource, UITableViewDelegate>, #property (weak, nonatomic) IBOutlet UITableView *tableview;,
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *costumeCell1 = #"Cell1";
AppDetailCell1 *cell1 = [tableView dequeueReusableCellWithIdentifier:costumeCell1];
if (!cell1) {
cell1 = [[AppDetailCell1 alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:costumeCell1];
}
cell1.appIconImageView.image = self.appIcon;
cell1.detailAppNameTextView.text = self.detailAppName;
cell1.developerLabel.text = [NSString stringWithFormat:#"By %#", self.appDeveloper];
return cell1;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
7; I build the project, but I only can find a blank UITableView
I made it the same way as I have done it with the other reusable TableViewCell in an other UIViewController.
Anyone have an idea how I can solve my problem?
Related
Please if you are going to add the link of the documentation, please don't do that
I have a problem her and i don't know how to solve it and need a clear answer
I have build a table view from xcode UI and add 5 sections each section contains some cells except section2, what I want to do is to add cells to section2 in viewDidLoaded is that possible or not
this is the header file
#interface Menu : UITableViewController;
this is the implementation file
#implementation Menu
#synthesize drawerTableView;
- (void) viewDidLoad {
NSDictionary *object = [drawerTableView dataSource];
KhawaterDataManager *sharedManager = [KhawaterDataManager instance];
CategoriesResponse *categories = [sharedManager categories];
[categories printObject];
}
/*- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"%d", section);
switch (section) {
case 1:
return 5;
break;
}
return [tableView.dataSource[section] count];
}*/
/*- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
[cell setBackgroundColor:[UIColor colorWithRed:.8 green:.8 blue:1 alpha:1]];
cell.textLabel.text = #"hello";
return cell;
}*/
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)newIndexPath{
// my logic
}
#end
I think you are using static cells in your UITableView. What you can do is make use of dynamic tableview cells. You have to uncomment and use both methods to create your cell:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
I am relative new to iOS development. Right now, I created 2 ViewController using storyboard. The one consist one button that lead into another controller using segue (show).
This controller is TableViewController that embedded in Navigation Controller and already connected with its responsible class that inherit from UITableViewController.
My problem is this page doesn't load its data (NSMutableArray) that already initialized in viewDidLoad using
_dataClient = [NSMutableArray arrayWithObjects:#"First City",#"Second City",#"Third City",#"Forth City",#"Fift City", nil];
This is my table delegate and datasource:
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 0;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [_dataClient count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *cellIdentifier = #"cellItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
// Configure the cell...
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = [_dataClient objectAtIndex:indexPath.row];
return cell;
}
Is there any step that I forgot to do?
You must return 1 section at least. Change this line:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1; /// here
}
I have created a UITableView in Storyboard and it is dynamically cell. The problem is that when there are not enough cells to reuse, it randomly empties a few of my cells. I think this is logical, but I want to resolve this problem.
I give an example:
I have a UITableView that is capable to generate 10 cells in a view. But now, I only want to show 8 cells out of 10. It gives no problem when I have only a section. With more than 1 section, it will always empty 2 cells and show 8 cells, but it should show 10 cells.
Can anyone help me with this? Thank you.
Updated With Source code
#pragma mark - List View
#pragma mark - Table View Delegate
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section {
// Number of rows is the number of time zones in the region for the specified section.
return self.listCollection.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ListCell" forIndexPath:indexPath];
for (id object in cell.contentView.subviews) {
[object removeFromSuperview];
}
[cell.contentView addSubview:[self.listCollection objectAtIndex:indexPath.row]];
return cell;
}
self.listCollection has an array of UIView Object.
Updated With Images:
Image 1
Image 2
It is happening because you are using 2 sections but are not specifying the content for each section separately. To understand this we need to look into the description of addSubview: method from Apple Documentation
This method establishes a strong reference to view and sets its next responder to the receiver, which is its new superview.
Views can have only one superview. If view already has a superview and that view is not the receiver, this method removes the previous superview before making the receiver its new superview.
Have a good look at bold section in second paragraph. As you are using the same view object from listCollection to populate both the section, so newest created cell will become the superview for this view object and previous cell will be left out with nothing but the plane contentView. You can get the real feel by assigning some default color to the cell contentView. Your blank cell will be displaying the color in full content while other cells will display the view
cell.contentView.backgroundColor = [UIColor greenColor];
Solution
I will recommend to use 2 different datasource for both sections as explained below.
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section {
// Number of rows is the number of time zones in the region for the specified section.
if(section==0)
return self.listCollection.count;
else
return <row count for section 1>
}
Same way you need to modify the cellForRowAtIndexPath: code for each section.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ListCell" forIndexPath:indexPath];
for (id object in cell.contentView.subviews) {
[object removeFromSuperview];
}
if(section==0)
[cell.contentView addSubview:[self.listCollection objectAtIndex:indexPath.row]];
else
[cell.contentView addSubview:[<second array of views> objectAtIndex:indexPath.row]];
return cell;
}
But if that is your case that you have to use same array, then you can use this technique. Thanks to Rishi for that.
Last but not least, you should use a custom UITableViewCell class as Michal Zygar has suggested in his post.
UIView *tempView = [self.listCollection objectAtIndex:indexPath.row];
NSData *tempArchiveView = [NSKeyedArchiver archivedDataWithRootObject:tempView];
UIView *viewOfSelf = [NSKeyedUnarchiver unarchiveObjectWithData:tempArchiveView];
[cell.contentView addSubview:viewOfSelf];
You are using the UITableView wrong way.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ListCell" forIndexPath:indexPath];
for (id object in cell.contentView.subviews) {
[object removeFromSuperview];
}
[cell.contentView addSubview:[self.listCollection objectAtIndex:indexPath.row]];
return cell;
}
This is highly inapriopriate. Your listCollection should contain model data. In - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath you should configure the cell with this data.
So you should subclass the UITableViewCell for example
#interface ApartmentCell:UITableViewCell
#property (weak, nonatomic) UILabel* floor;
#property (weak, nonatomic) UILabel* unit;
#property (weak, nonatomic) UILabel* type;
#property (weak, nonatomic) UILabel* area;
#property (weak, nonatomic) UILabel* price;
#end
and then
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ApartmentCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ListCell" forIndexPath:indexPath];
Apartment* apartment=self.listCollection[indexPath.row];
cell.unit.text=apartment.unit;
//and so on with other fields
return cell;
}
So I've used this tutorial to populate a UITableView with custom cells that represent balances. When stepping through the code, I witness the correct amount of cells get created (only 4 with the current test data) and their labels' text set correspondingly.
My problem is when the table is displayed on the screen, only the first row/cell is displayed.
Any insight as to why this could be occurring would be greatly appreciated!
Removed old code.
BalanceCell.h:
#import <UIKit/UIKit.h>
#interface BalanceCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UILabel *nameLabel;
#property (weak, nonatomic) IBOutlet UILabel *amountLabel;
#property (weak, nonatomic) IBOutlet UILabel *modifiedLabel;
#end
EDIT:
My TableView delegate methods are now as follows:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return [_balances count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
BalanceCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[BalanceCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.backgroundColor = [_hex colorWithHexString:_themeColourString];
return cell;
}
-(void)tableView:(UITableView *)tableView willDisplayCell:(BalanceCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
Balance *item = [_balances objectAtIndex:indexPath.row];
cell.nameLabel.textColor = _themeColour;
cell.nameLabel.text = item.name;
cell.amountLabel.textColor = _themeColour;
cell.amountLabel.text = [NSString stringWithFormat:#"%#%#", item.symbol, item.value];
cell.modifiedLabel.textColor = _themeColour;
cell.modifiedLabel.text = [NSString stringWithFormat:#"%#", item.modified];
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 94;
}
As #Sebyddd suggested, I now register the NIB in the viewDidLoad method.
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerNib:[UINib nibWithNibName:#"BalanceCell" bundle:nil] forCellReuseIdentifier:#"Cell"];
}
These changes may make my code more correct but still only the first cell is displayed.
If cells are getting created and returned properly I guess height is not being set propery. By default I beleive all cells have a height of 44. If your cell exceeds this height it might not get displayed.
You can tell the tableview to adjust height for every cell using (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath delegate
In that delegate just return your cells height.
EDIT:
You are using dequeueReusableCellWithIdentifier: which will return A UITableViewCell object with the associated identifier or nil if no such object exists in the reusable-cell queue.
Instead use dequeueReusableCellWithIdentifier:forIndexPath: which will return A UITableViewCell object with the associated reuse identifier. This method always returns a valid cell.
You need to register the nib/class for that custom cell in viewDidLoad
Try this:
if (cell == nil) {
[tableView registerNib:[UINib nibWithNibName:#"BalanceCell" bundle:nil] forCellReuseIdentifier:#"Cell"];
cell = [[BalanceCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
Use this tuto : http://www.appcoda.com/uitableview-tutorial-storyboard-xcode5/ , your tuto is a bit outdated, and hard to follow !
I'm doing this iPhone project where I need to have a (dynamic) table view inside a normal view controller. I didn't choose a Table View Controller because I need to put other stuff in the page. Imagine a page with text fields, buttons and my small table view of about 4-5 cells.
When I run the app, I need to touch a button to segue to this view. The I click the button, the app crashes and tells me that:
2012-07-22 14:40:57.304 How Many?[3055:f803] * Assertion failure in
-[UITableView _createPreparedCellForGlobalRow:withIndexPath:], /SourceCache/UIKit_Sim/UIKit-1914.84/UITableView.m:6061
This is my .H file:
#import <UIKit/UIKit.h>
#interface ProjectViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
#end
This is my .M file:
#import "ProjectViewController.h"
#interface ProjectViewController ()
#end
#implementation ProjectViewController
//MyViewController.m
#pragma mark - Table View Data Source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
NSLog(#"numberOfSectionsInTableView");
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"numberOfRowsInSection");
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"cellForRowAtIndexPath");
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
NSLog(#"cellForRowAtIndexPath");
cell.textLabel.text = #"Test";
return cell;
}
#end
I control-dragged from the table view to my controller to set the delegate and the datasource.
What did I do wrong??
Thanks for your help.
Try to make an outlet in your .h file and wire it to the tableView in your storyboard
ProjectViewController.h
#property (nonatomic, strong) IBOutlet UITableView *myTableView;
ProjectViewController.m
#synthesize myTableView;
...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"cellForRowAtIndexPath");
UITableViewCell *cell = [self.myTableView dequeueReusableCellWithIdentifier:#"cell"];
NSLog(#"cellForRowAtIndexPath");
cell.textLabel.text = #"Test";
return cell;
}
In your -cellForRowAtIndexPath, if you do this, you will be fine.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"cellForRowAtIndexPath");
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if(cell == nil)
{
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"cell"];
}
NSLog(#"cellForRowAtIndexPath");
cell.textLabel.text = #"Test";
return cell;
}
The problem is your cell never got memory allocated and initialized. That's why you get the error.