What is wrong with this code? The image is not displayed. Appreciate any help...
Stepping through the code, I can see that all the variables are updated correctly. The code executes without any errors. The image is not seen though.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ModuleViewCellId = #"ModuleViewCellId";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ModuleViewCellId];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ModuleViewCellId] autorelease];
}
NSUInteger row = [indexPath row];
NSDictionary *step = [self.module.steps objectAtIndex:row];
cell.textLabel.text = [step objectForKey:kStepTitleKey];//;
cell.textLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size:14.0];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.backgroundColor = [UIColor clearColor];
cell.indentationWidth = 50;
cell.indentationLevel = 1;
//2/6 shp - add icons to the table view
NSString *imagename = [step objectForKey:kStepIconKey];
NSLog(#"%#",imagename);
UIImageView *image;
image = [[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 57, 57)] autorelease];
image.tag = 1000 + row;
image.contentMode = UIViewContentModeScaleAspectFit;
image.hidden = FALSE;
[image setImage: [UIImage imageNamed:imagename]];
[cell.contentView addSubview:image];
return cell;
}
I just found the answer. The problem was with the path to the file names. All my image files are stored in a bundle. So even though the image file names are correctly referenced, the path needed to be appended.
Adding the path this way fixed the problem.
NSString *imagename = [NSString stringWithFormat: #"%#%#", #"Assets.bundle/assets_dir/",[step objectForKey:kStepIconKey]];
This answer also helped me. UITableViewCell with images in different dimensions
Since you are using default cell i.e uitableViewCell, make use of imageview property of the cell.
UITableViewCell *cell =[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
cell.imageView.image = [UIImage imageNamed:#"ImageName"];
cell.imageView.contentMode = UIViewContentModeScaleAspectFit;
Related
I am using table view using custom coding with tag method to save memory.
I was successful to show data in the view but the problem is if 10 cells are showing and then if I scroll down like for one cell then it should show 2-11 cell data but it switches to 1-10 again.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"cellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
UILabel *cellNAMElabl = nil;
UILabel *cellDetaillabl = nil;
UIImageView *imgView = nil;
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
cellNAMElabl = [[UILabel alloc] initWithFrame:CGRectMake(88, 10, 150, 20)];
[cellNAMElabl setTag:1];
cellNAMElabl.text = [name5 objectAtIndex:indexPath.row];
UIFont *myFont1 = [ UIFont fontWithName: #"Arial" size: 20.0 ];
cellNAMElabl.font = myFont1;
[cell.contentView addSubview:cellNAMElabl];
cellDetaillabl = [[UILabel alloc] initWithFrame:CGRectMake(88, 28, 150, 20)];
[cellDetaillabl setTag:2];
cellDetaillabl.text = [email5 objectAtIndex:indexPath.row];
UIFont *myFont = [ UIFont fontWithName: #"Arial" size: 13.0 ];
cellDetaillabl.font = myFont;
[cell.contentView addSubview:cellDetaillabl];
imgView=[[UIImageView alloc] initWithFrame:CGRectMake(25, 5, 52, 50)];
[imgView setTag:3];
imgView.image = [imagepath5 objectAtIndex:indexPath.row];
[cell.contentView addSubview:imgView];
}
cellNAMElabl = (UILabel *)[cell viewWithTag:1];
cellDetaillabl = (UILabel*)[cell viewWithTag:2];
imgView = (UIImageView*)[cell viewWithTag:3];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
You are not assigning new content to subviews, if they have been already created. After the case if(cell == nil), these you have just got references.
cellNAMElabl = (UILabel *)[cell viewWithTag:1];
cellDetaillabl = (UILabel*)[cell viewWithTag:2];
imgView = (UIImageView*)[cell viewWithTag:3];
Here when cell is not nil, you are just getting references to labels and imageview, but you are not setting new text and image from data source. Add following lines and remove them from the if (cell == nil) part:
cellNAMElabl.text = [name5 objectAtIndex:indexPath.row];
cellDetaillabl.text = [email5 objectAtIndex:indexPath.row];
imgView.image = [imagepath5 objectAtIndex:indexPath.row];
[cell.contentView addSubview:imgView];
The way this dequeueReusableCellWithIdentifier works: If iOS detects that a cell is not displayed anymore, then dequeueReusableCellWithIdentifier will return that cell. If there is no unused cell, it returns nil. So what you need to do:
If dequeueReusableCellWithIdentifier returns nil, then you create a new cell, and you do all the setup that is required for all cells with the same identifier. For example, add view tags like you did, set fonts, colors etc.
Then, whether you use a cell returned by dequeueReusableCellWithIdentifier or one that you just created yourself, you add all the information that is used for the specific section/row that you want to display. So if row 1, row2, and so on display different text, then you set the text here. That's what you didn't do, so when a cell was reused, you didn't set the new text for it.
So the idea is that all the work that is the same for all rows is only done once when a cell is created, and only as many cells are created as is needed to display them on the screen. The work that is different from row to row is done for each row, as it is needed.
If you set a breakpoint in the if cell == nil block its probably only being hit for the first set if your reuseID is correct. Thats why its never getting a chance to set any new data into the cell.
You should not look for a nil cell, rather use a correct reuseID and a prototype cell in IB that is set to a custom UITableViewCell subclass you create.
Its also good practice to implement prepareForReuse on custom cells, where you clear any cell data e.g. label.text = nil, imageview.image = nil
This way you dont get invalid data from previously dequeued cells. It might not solve the question directly, but it would have wiped the fixed data set in your if cell == nil block to help debug.
What you want to do is..
add/setup the tableViewCell UI if the cell is nil..
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"cellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
UILabel *cellNAMElabl = [[UILabel alloc] initWithFrame:CGRectMake(88, 10, 150, 20)];
cellNAMElabl.tag = 1;
cellNAMElabl.font = [UIFont fontWithName: #"Arial" size: 20.0 ];
[cell.contentView addSubview:cellNAMElabl];
UILabel *cellDetaillabl = [[UILabel alloc] initWithFrame:CGRectMake(88, 28, 150, 20)];
cellDetaillabl.tag = 2;
cellDetaillabl.font = [UIFont fontWithName: #"Arial" size: 13.0 ];
[cell.contentView addSubview:cellDetaillabl];
UIImageView *imgView=[[UIImageView alloc] initWithFrame:CGRectMake(25, 5, 52, 50)];
imgView.tag = 3;
[cell.contentView addSubview:imgView];
}
//and just update your data if the cell is currently exist and not nil..
//you already called the view using tag so, you dont need those:
// UILabel *cellNAMElabl = nil;
// UILabel *cellDetaillabl = nil;
// UIImageView *imgView = nil;
((UILabel *)[cell viewWithTag:1]).text = [name5 objectAtIndex:indexPath.row]; // cellNAMElabl
((UILabel*)[cell viewWithTag:2]).text = [email5 objectAtIndex:indexPath.row]; // cellDetaillabl
((UIImageView*)[cell viewWithTag:3]).image = [imagepath5 objectAtIndex:indexPath.row]; // imgView
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
hope this have help you, happy coding cheers!
I am loading a UITableView in this way:
- (UITableViewCell *)tableView:(UITableView *)tableViewLocal cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
CustomTableViewCell *cell = [tableViewLocal dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
for(UIView *subview in cell.contentView.subviews)
{
[subview removeFromSuperview];
}
UIImage* img;
UIImageView *imv = [[UIImageView alloc]initWithFrame:CGRectMake(5, 5, 60, 60)];
if(isFiltered == TRUE){
cell.textLabel.text = [filteredTableData objectAtIndex:indexPath.row];
cell.textLabel.font = [UIFont systemFontOfSize:14];
}
if(isFiltered == FALSE){
cell.textLabel.text = [itemArray objectAtIndex:indexPath.row];
cell.textLabel.font = [UIFont systemFontOfSize:14];
cell.detailTextLabel.text = [NSString stringWithFormat:#"date added: %#", [DKStoreManager dateFileWasCreatedWithFileName:[itemArray objectAtIndex:indexPath.row] inFolderNumber:[_FolderCode intValue] forUser:[_PassedUserID intValue] andType:_FolderType]];
}
NSData* data = [DKStoreManager loadFileWithName:[itemArray objectAtIndex:indexPath.row] forFolderNumber:[_FolderCode intValue] forUser:userID andType:_FolderType];
img = [[UIImage imageWithData:data] cropToSize:CGSizeMake(320, 320) usingMode:NYXCropModeCenter];
imv.image = img;
[cell.contentView addSubview:imv];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
As you can see I have an itemArray with all the names of the files, and for each cell I load the relative NSData in this way:
NSData* data = [DKStoreManager loadFileWithName:[itemArray objectAtIndex:indexPath.row] forFolderNumber:[_FolderCode intValue] forUser:userID andType:_FolderType];
Since it also loads images (and there may be more than 300 cells), the UI frees.
I have tried loading only the visible cells using the accepted answer of this link:
tableView: cellForRowAtIndexPath: get called not only for visible cells?
however all of the cells are loaded at the same time. I have no idea of how to do this...
cellForRowAtIndexPath gets called when the tableView reloads as well as when the user scrolls. The UI freeze could be due to the fact that your calling
for(UIView *subview in cell.contentView.subviews)
{
[subview removeFromSuperview];
}
UIImageView *imv = [[UIImageView alloc]initWithFrame:CGRectMake(5, 5, 60, 60)];
which means that every time the user scrolls , you are iterating through all the subViews and removing them, as well as allocating UIimageView's at the same time, this is not a good way to go about displaying content. You can use the tableViewCell's default imageView property to display your image. After getting you image just say
cell.imageView.image = img;
hello I am beginner in iOS I have created custom table view and I have Two array then I want to set both array data together in simultaneously one by one cell content in table view I show image which i want..
Please refer : http://i.stack.imgur.com/WIkaf.png
NSMutableArray *SearchPatientCode;
NSMutableArray *SearchPatientName;
UITableView *table_SearchPatient;
SearchPatientCode=[[NSMutableArray alloc]initWithObjects:#"PH230130420",#"PH230420321",#"Ph450362120", nil];
SearchPatientName=[[NSMutableArray alloc]initWithObjects:#"Rahul Sharma",#"Amit kumar",#"anil sharma", nil];
table_SearchPatient=[[UITableView alloc]initWithFrame:CGRectMake(130,40,170,250)style:UITableViewStylePlain];
table_SearchPatient.delegate=self;
table_SearchPatient.dataSource=self;
table_SearchPatient.layer.borderWidth = 2.0;
table_SearchPatient.layer.borderColor = [UIColor grayColor].CGColor;
[self.view addSubview:table_SearchPatient];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if(tableView==table_SearchPatient)
{
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] ;
}
cell.textLabel.text =[NSString stringWithFormat:#"%# /n %#",[SearchPatientCode objectAtIndex:indexPath.row],[SearchPatientName objectAtIndex:indexPath.row]];
cell.textLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size:10.0f];
// cell.detailTextLabel.text=[SearchPatientName objectAtIndex:indexPath.row];
}
return cell;
}
I am using this But this is not show as I want ...Solve this problem!!
Add New UILable with numberOfLines = 2 like bellow...
if you want to unlimited line with your content data then you can do it with set numberOfLines = 0 and set lineBreakMode = UILineBreakModeWordWrap
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if(tableView==table_SearchPatient)
{
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] ;
}
UILabel *lbl = [[UILabel alloc]init];
lbl.text = [NSString stringWithFormat:#"%# /n %#",[SearchPatientCode objectAtIndex:indexPath.row],[SearchPatientName objectAtIndex:indexPath.row]];
lbl.font = [UIFont fontWithName:#"Helvetica-Bold" size:10.0f];
[lbl setFrame:CGRectMake(20, 2, 250, 35)];// set frame which you want
[lbl setBackgroundColor:[UIColor clearColor]];// set any color here
// lbl.lineBreakMode = UILineBreakModeWordWrap; // set it if you want to height of UILable with its content (Multiple line)
lbl.numberOfLines = 2;// Add this line // Set 0 if you want to multiple line.
[cell.contentView addSubview:lbl];
}
return cell;
}
You can use detail cell.detailTextLabel.text.
Or You can create a custom cell and add the labels to the cell like this
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] ;
}
cell.textLabel.text = #"";
label_name_one = [[[UILabel alloc]initWithFrame:CGRectMake(10, 10, 90, 20)]autorelease];
[label_name_one setText:[SearchPatientCode objectAtIndex:indexPath.row]];
label_name_two = [[[UILabel alloc]initWithFrame:CGRectMake(92, 30, 170, 80)]autorelease];
[label_name_two setText:[SearchPatientCode objectAtIndex:indexPath.row]];
set the RectFrame according to your requirements.
Firstly change your cell style as UITableViewCellStyleValue2 then Use this code for multiline text in cell :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString * cellIdentifier = #"MyIdentifier";
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2
reuseIdentifier:cellIdentifier];
[[cell textLabel] setFont:[UIFont fontWithName:#"Helvetica-Bold" size:10.0f]];
}
[[cell detailTextLabel] setText:[NSString stringWithFormat:#"%# %#",[SearchPatientCode objectAtIndex:indexPath.row],[SearchPatientName objectAtIndex:indexPath.row]]];
cell.detailTextLabel.numberOfLines = 2;
cell.detailTextLabel.lineBreakMode = NSLineBreakByWordWrapping;
return cell;
}
Hope it helps you.
Also make sure you check out the free Sensible TableView framework. Given the arrays, the framework will automatically display all the values in the table view, and will even generate detail views where applicable. Saves me tons of time.
I have a UITable that reuses cells. Each cell has an image dependant on a condition. The correct images are always used however when cells are reused the old image is displayed behind the new one. I have tried to remove the uiimageview before adding a new subview however it has no effect.
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpTableIden = #"simpTableIden";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpTableIden];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpTableIden];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"name"];
CGRect picFrame = CGRectMake(cell.frame.size.width-cell.frame.size.height, 0, cell.frame.size.height, cell.frame.size.height);
UIImage *greyDot = [UIImage imageNamed:#"greyDot.png"];
UIImage *whiteDot = [UIImage imageNamed:#"whiteDot.png"];
UIImageView *achievImg = [[UIImageView alloc] init];
tableView.backgroundColor = [UIColor clearColor];
achievImg.frame=picFrame;
if ([[[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"achieved"] boolValue]) {
achievImg.image = whiteDot;
}
else {
achievImg.image = greyDot;
}
[achievImg removeFromSuperview];
[cell.contentView addSubview:achievImg];
return cell;
}
Any help would be greatly appreciated?
The problem is each time cellForRowAtIndexPath: is called you create a new imageview.
I corrected your code as follows:
Here we create an imageView once for each new new cell and replace it's image every time cellForRowAtIndexPath: is called:
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpTableIden = #"simpTableIden";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpTableIden];
UIImageView *achievImg = nil;
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpTableIden];
//New Cell ... Create Image view
achievImg = [[UIImageView alloc] init];
achievImg.tag = 10;
[cell.contentView addSubview:achievImg];
}
else{
//Old cell...get previously createdd imageview
achievImg = (UIImageView*)[cell.contentView viewWithTag:10];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"name"];
CGRect picFrame = CGRectMake(cell.frame.size.width-cell.frame.size.height, 0, cell.frame.size.height, cell.frame.size.height);
UIImage *greyDot = [UIImage imageNamed:#"greyDot.png"];
UIImage *whiteDot = [UIImage imageNamed:#"whiteDot.png"];
tableView.backgroundColor = [UIColor clearColor];
achievImg.frame=picFrame;
if ([[[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"achieved"] boolValue]) {
achievImg.image = whiteDot;
}
else {
achievImg.image = greyDot;
}
//You don't need this because it doesn't have a superview in the first place..it's new
//[achievImg removeFromSuperview];
return cell;
}
try like this,
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpTableIden = #"simpTableIden";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpTableIden];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpTableIden];
NSUInteger row = [indexPath row];
cell.textLabel.text = [[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"name"];
CGRect picFrame = CGRectMake(cell.frame.size.width-cell.frame.size.height, 0, cell.frame.size.height, cell.frame.size.height);
UIImage *greyDot = [UIImage imageNamed:#"greyDot.png"];
UIImage *whiteDot = [UIImage imageNamed:#"whiteDot.png"];
UIImageView *achievImg = [[UIImageView alloc] init];
tableView.backgroundColor = [UIColor clearColor];
achievImg.frame=picFrame;
if ([[[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"achieved"] boolValue]) {
achievImg.image = whiteDot;
}
else {
achievImg.image = greyDot;
}
[achievImg removeFromSuperview];
[cell.contentView addSubview:achievImg];
}
return cell;
}
You are always adding the imageView to the contentView of the cell. If the cell is reused that will lead to multiple imageViews in cell.
You can give a tag to the imageView. Always check if there is a view will same tag in the contentView of cell. If not add the imageView.
UIImageView *achievImg = (UIImageView *)[cell.contentView viewWithTag:55];
if(!achievImg){
achievImg = [[UIImageView alloc] init];
achievImg.tag = 55;
[cell.contentView addSubView:achievImg];
}
I need to display the cell data. Actually if I debug the code I can see that the cell.label.text does have correct value, but nothing is getting displayed on the simulator. I have set the row count in numberOfRowsInSection method.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"Cell";
LogTableCell *cell = (LogTableCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
CGRect frame1 = [ self.view frame];
frame1.origin.x=22.0f;
frame1.origin.y=55.0f;
frame1.size.width = 298.0f;
frame1.size.height= 425.0f;
[self.view.superview setFrame:frame1];
int btnWidth = ((self.view.frame.size.width-16)/3);
if(cell == nil)
{
cell = [[LogTableCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
LogItem *lg = [[LogItem alloc]init];
lg = [arrLogs objectAtIndex:indexPath.row ];
NSLog(#"%d",indexPath.row);
cell.lblname.textColor=[UIColor whiteColor];
cell.lblsubtype.textColor=[UIColor whiteColor];
cell.lbltime.textColor=[UIColor whiteColor];
cell.lblname.font=[UIFont fontWithName:#"Merriweather" size:15.0];
cell.lblsubtype.font=[UIFont fontWithName:#"Merriweather-Light" size:13.0];
cell.lbltime.font=[UIFont fontWithName:#"Merriweather-Light" size:13.0];
UIImageView *imageview = [[UIImageView alloc] initWithFrame:CGRectMake(1, cell.contentView.frame.size.height, 298.0,2)] ;
imageview.image = [UIImage imageNamed: #"lineseperator.png"];
[cell.contentView addSubview:imageview];
cell.lblname.text = lg.name;
NSLog(#"%#",lg.name);
[[cell imgtype] setImage:[UIImage imageNamed:lg.imagetype]];
if([lg.subtype length] == 0){
NSLog(#"%#",lg.subtype);
cell.lblsubtype.text = lg.time;
cell.lbltime.text = #"";
}
else{
NSLog(#"%#",lg.subtype);
cell.lblsubtype.text = lg.subtype;
cell.lbltime.text = lg.time;
}
return cell;
}
The imageview you're adding to the cell is covering all other content. You'll need to either resize/reposition it, or just use the already existing cell.imageView instead.