I have noticed that UITableViewCell is not reusing it's subviews and seems to be released when scrolling up and down. I am creating UITableViewCell subview and animating it on viewDidAppear. I want to do this only once and then I expect subview to stay in the ContentView forever until view disappears. So I have done following which I think right way but not sure what's wrong; can someone help?
UINib *nib1 = [UINib nibWithNibName:#"CustomCell" bundle:nil];
[self.tableView registerNib:nib1 forCellReuseIdentifier:#"CustomCell"];
#interface CustomCell : UITableViewCell
#property (nonatomic) IBOutlet UILabel *title;
#property (nonatomic) CustomeView *customeView;
#end
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString cellIdentifier = #"CustomCell";
CustomCell *customCell = [tableView dequeueReusableCellWithIdentifier:accountCellIdentifier forIndexPath:indexPath];
......
customCell.customeView = (CustomeView*)[customCell.contentView viewWithTag:101];
if(!customCell.customeView) {
customCell.customeView = [CustomeView new];
//configure customview...
customCell.customeView.tag = 101;
[customCell.contentView addSubview:customCell.customeView];
}
return cell;
}
Try to change your property type to strong:
#property (strong, nonatomic) CustomeView *customeView;
Related
I am adding a custom UITableViewCell to a UITableView in storyboard - via the prototype cell and a class file. When run, the row height is correct, but the content is still using the default with cell.textLabel.text, not my [cell.horseName setText:#"string"] setting.From reading the other posts on StackOverflow I've added:
RankingsTableViewController.m:viewDidLoad:
[self.tableView registerClass:[RankingTableViewCell class]
forCellReuseIdentifier:#"raceRankingCell"];
And also tried replacing:
RankingTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
with:
RankingTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[RankingTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
With no effect.
Here is what the storyboard looks like for the table:
From the tree view, you can see the Cell Identifier is raceRankingCell, in the Connections inspector, they are all hooked up to the class file:
Code:
RankingTableViewCell.h
#import <UIKit/UIKit.h>
#interface RankingTableViewCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UILabel *raceLabel;
#property (weak, nonatomic) IBOutlet UILabel *horseNameLabel;
#property (weak, nonatomic) IBOutlet UILabel *jockeyLabel;
#property (weak, nonatomic) IBOutlet UILabel *rankingLabel;
#property (weak, nonatomic) IBOutlet UILabel *programIdLabel;
#property (weak, nonatomic) IBOutlet UIImageView *horseImage;
#end
RankingTableViewController.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"raceRankingCell";
RankingTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
/* Test#1- no change in behavior
RankingTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[RankingTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
*/
// Any data yet? If not, show the no data yet cell
if([_raceResultsArray count] < 1) {
DLog(#"No race results yet");
[cell.horseNameLabel setText:#"Data is loading... - horseName"];
cell.textLabel.text = #"Data is loading... - textLabel";
When I use the line cell.textLabel.text = #"Data is loading... - textLabel"; the string is displayed.
What am I missing?
When a cell is defined in a storyboard, you shouldn't register the class. Registering a class means the table view will get the cell (including all its subviews) from the class implementation, so it should only be used when you've defined the cell wholly in code (no xib or storyboard). Deleting that line should fix your problem.
Try this.
RankingTableViewCell *cell = (RankingTableViewCell*)[self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
I used to work like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryNone;
}
But now I have to do the same thing on a cell that is not a UITableViewCell:
I had to put in cells a lot of stuff, so i couldn't use normal UITableViewCells, and I made it my own (called PrototypeTableViewCell). Like this:
#interface PrototypeTableViewCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UILabel *eventTitle;
#property (weak, nonatomic) IBOutlet UILabel *eventLocation;
#property (weak, nonatomic) IBOutlet UILabel *eventStartDate;
#property (weak, nonatomic) IBOutlet UILabel *eventEndDate;
#end
So how can I do the things I used to do on normal TableViewCells (like setting the accessory:checkmark)?
"cellForRowAtIndexPath:indexPath" won't work with the class I created.
Your PrototypeTableViewCell is a subclass of UITableViewCell. All you need to do is simply cast UITableViewCell to your PrototypeTableViewCell as follows:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// cast UITableViewCell to your PrototypeTableViewCell
PrototypeTableViewCell *cell = (PrototypeTableViewCell*)[tableView cellForRowAtIndexPath:indexPath];
// use its properties as normal
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
I have created a subclass of UITableViewCell and I called it DCCustomCell. This is the DCCustomCell.h file.
#import <UIKit/UIKit.h>
#interface DCCustomCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#property (weak, nonatomic) IBOutlet UILabel *title;
#property (weak, nonatomic) IBOutlet UILabel *date;
#property (weak, nonatomic) IBOutlet UILabel *price;
#end
All the proprieties are correcty connected with elements in my iPhone.storyboard file.
I also selected the tableViewCell in iPhone.storyboard and i setted my cell's identifier to "CustomCell" and the class to DCCustomCell.
This is the UITableViewController's viewDidLoad method:
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.delegate = self;
self.tableView.dataSource = self;
[self.tableView registerClass:[DCCustomCell class] forCellReuseIdentifier:#"CustomCell"];
// Do any additional setup after loading the view, typically from a nib.
}
and this is the tableView:cellForRowAtIndexPath: method:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"CustomCell";
DCCustomCell *cell = (DCCustomCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
NSLog(#"%#" ,cell);
cell.imageView.image = [UIImage imageNamed:#"info_button.png"];
cell.title.text = #"Hello!";
cell.date.text = #"21/12/2013";
cell.price.text = #"€15.00";
return cell;
}
The problem is that the imageView is correctly setted, but all the labels are blank. If I change the imageView property name to, for example, eventImageView, the image will not be setted.
This is the result:
I can't figure out how I can solve this problem.
EDIT: if I remove
[self.tableView registerClass:[DCCustomCell class] forCellReuseIdentifier:#"CustomCell"];
from viewDidLoad all seems to work. why?
As you noticed it works when you remove
[self.tableView registerClass:[DCCustomCell class] forCellReuseIdentifier:#"CustomCell"];
You only have to do this if you use dequeueReusableCellWithIdentifier:indexPath: AND have not already set the custom class in the identity inspector for that cell. If you use registerClass: forCellReuseIdentifier the cell will be initialized with initWithStyle:reuseIdentifier: instead of initWithCoder: thus screwing up your connections you made in the storyboard.
Have you bind the Controls to IBOutlet ?
You can try setting DCCustomCell to UITableviewCell's class directly in Storyboard.
And than you need to set outlets with controls in cell
Try:
if (cell == null) {
//create and initialize cell
}
after
DCCustomCell *cell = (DCCustomCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
You first check your outlets properly that all the labels are connected & write this also :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"CustomCell";
DCCustomCell *cell = (DCCustomCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"DCCustomCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
NSLog(#"%#" ,cell);
cell.imageView.image = [UIImage imageNamed:#"info_button.png"];
cell.title.text = #"Hello!";
cell.date.text = #"21/12/2013";
cell.price.text = #"€15.00";
return cell;
}
I have a class named FirstViewController which is a subclass of UIViewController and I have a UITableView in the class. I need to transition from this class to a new UIViewController subclass (using segues) when a row is pressed.
I have made the FirstViewController the UITableViewDelegate and UITableViewDataSource using the code -
#interface FirstViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
I am getting an error on this line of code -
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
How do I fix this problem since the tableView is found in UITableViewController and not in UIViewController class ?
Edit -
Here's the code related to my table view -
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [sarray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellId = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if(cell == nil){
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
}
NSString *text = [sarray objectAtIndex:[indexPath row]];
cell.textLabel.text = text;
return cell;
}
You can simply declare tableView as a property:
#property(nonatomic, strong) IBOutlet UITableView *tableView;
You get a free UITableView only if you subclass UITableViewController,
#interface FirstViewController : UITableViewController
you can simply declare a table view property on FirstViewController using:
#property(nonatomic, strong) IBOutlet UITableView *tableView;
you then need to connect this property to the Table View in the story board.
I've got a question on how to add a UIView to a UITableViewCell.
In my learning Project I've got a UITableViewController (TableTestViewController, a UITabelViewCell.xib (MainTabelCell.xib) and a UIView (InnerTableView).
My Goal ist to show the MainTableCell in the UITableView and in this MainTabelCell the InnerTabelView but I only manage to show the Cell in the Table.
TableTestViewController.h:
#import <UIKit/UIKit.h>
#import "InnerTableView.h"
#interface TableTestViewController : UITableViewController {
UITableView *mainTable;
UITableViewCell *nibLoadedCell;
InnerTableView *innerView;
}
#property(nonatomic, retain) IBOutlet UITableView *mainTable;
#property(nonatomic, retain) IBOutlet UITableViewCell *nibLoadedCell;
#property(nonatomic, retain) InnerTableView *innerView;
#end
TableTestViewController.m:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"MainTableCell"
owner:self options:NULL];
cell = nibLoadedCell;
}
// Configure the cell.
innerView = [[UIViewController alloc] init];
[cell addSubview: innerView.view];
return cell;
}
Does anyone have an Idea why the innerView will not be shown in the TabelViewCell? What did I miss here? I'm still learning all that stuff but after 5 hours I don't find a clue in my Books. Hope this is not a to dumb question :)
Thank you
CaptnCrash
You should use [cell.contentView addSubview:yourView];
BTW, in your code, your innerView is not released properly.