I have UITableView with Custom View on it.
For the bottom of the tableview, I add a "Load More" cell there.
After clicked, the tableview load more data successfully and the "Load More" cell still at the bottom of the tableview.
However, after I clicked the first "Load More", the second "Load More" appears, and the custom view still exist in the same cell of second "Load More". "Load More" and custom view are on the same cell. I want that cell only appear "Load More".
This problem exists for the third, fourth "Load More".
Can anyone help me?
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return imageCurPos+1;
}
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if([aTableView tag]==501){
// Main Table
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier];
[[cell viewWithTag:3007] removeFromSuperview];
const NSInteger BOTTOM_LABEL_TAG = 3002;
UIImageView *bottomLabel;
UILabel *loadMore;
if(indexPath.row < imageCurPos){
if (cell == nil)
{ //All repeat things come here, if don't want to repeat here, please state outside this brucket
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
//Edited
for (UIView *view in [cell.contentView subviews])
{
[view removeFromSuperview];
}
bottomLabel = [[[UIImageView alloc] initWithFrame: CGRectMake(50, 30, 250, 112)] autorelease];
[cell.contentView addSubview:bottomLabel];
bottomLabel.tag = BOTTOM_LABEL_TAG;
cell.backgroundView =
[[[UIImageView alloc] init] autorelease];
cell.selectedBackgroundView =
[[[UIImageView alloc] init] autorelease];
UIImageView *iconView = [[[UIImageView alloc] initWithFrame:CGRectMake(0, 30, 45, 45)] autorelease];
iconView.image = [UIImage imageNamed:#"02_bubble.png"];
[[cell contentView] addSubview:iconView];
bottomLabel.image = [UIImage imageNamed:#"05_bubble.png"];
}else if(indexPath.row == imageCurPos ){ //For Load More
if (cell == nil)
{ //All repeat things come here, if don't want to repeat here, please state outside this brucket
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
//Edited
for (UIView *view in [cell.contentView subviews])
{
[view removeFromSuperview];
}
loadMore =
[[[UILabel alloc]
initWithFrame:
CGRectMake( 0, 0, 300, 50)]
autorelease];
loadMore.text = #"Load more...";
loadMore.textAlignment = UITextAlignmentCenter;
loadMore.tag = 3007;
loadMore.textColor = [UIColor whiteColor];
loadMore.backgroundColor = [UIColor darkTextColor];
[cell.contentView addSubview:loadMore];
}
return cell;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *) indexPath{
if([tableView tag]==501){
if([indexPath row] != imageCurPos){
}else{ // For load more
NSLog(#"noRow Prev: %d", imageCurPos);
imageCurPos += interval;
NSLog(#"noRow After: %d", imageCurPos);
[tbl_mo_main reloadData];
}
}
I think you should use 2 different identifiers, one for the normal cell and one for load more cell.
And one thing is that creating custom cell should be done in the block.
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
// create the views in side the cell and add it
...
}
Then outside this block, update the cell.
You can set the tag for your views in the creation of cell, and update the corresponding view by getting it with [cell.contentView viewWithTag:tag]
You may refer to this topic: Reload TableViewCell's UILabels in dynamic table
[cell.contentView addSubview:loadMore];
This line adds the label to cell contentview but when the cell is reused ..that label is still present in that cell.
Add the following code after if(cell == nil) in both if and else for index path checking.
for (UIView *view in [cell.contentView subviews])
{
[view removeFromSuperview];
}
Related
I created a prototype cell in storyboard with four labels
then in my code i am adding different background images for first,last and other rows.
for first row all 4 labels are hidden.
Intially all 5 rows shown in screen appear good.but when i scroll up to see 6th row ,it behaves like first row and all 4 labels are hidden.
here is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
Employee *currentEmployee=[Employee sharedData];
NSArray *tempArray =currentEmployee.leaveApproveDict;
static NSString *simpleTableIdentifier = #"approveLeaveCell";
approveLeaveCell *cell = [self.approveLeaveView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[approveLeaveCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
if([tempArray count]!=0){
if(indexPath.row == 0){
UIImageView *imgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"h_t_top_bar.png"]];
cell.backgroundView = imgView;
cell.fromLabel.hidden=YES;
cell.toLabel.hidden=YES;
cell.typeLabel.hidden=YES;
cell.nameLabel.hidden=YES;
[cell setUserInteractionEnabled:NO];
}
else{
if(indexPath.row ==[tempArray count]){
UIImageView *imgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"h_t_bottom_bar.png"]];
cell.backgroundView = imgView;
}
else{
UIImageView *imgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"h_t_repeat_bar.png"]];
cell.backgroundView = imgView;
}
//assign the data
if(indexPath.row-1 < [tempArray count]){
NSDictionary *tempLeave= [currentEmployee.leaveApproveDict objectAtIndex:indexPath.row-1];
cell.toDateLabel.text=[self extractLeaveDate:(NSString*) [tempLeave objectForKey:#"leaveTo"]];
cell.fromDateLabel.text=[self extractLeaveDate:(NSString*)[tempLeave objectForKey:#"leaveFrom"]];
cell.leaveLabel.text=[tempLeave objectForKey:#"leaveType"];
cell.employeeNameLabel.text=[tempLeave objectForKey:#"requesterName"];
}
}
return cell;
}
The same issue happens with me. I have solved it using two different customized UITableViewCell and two identifiers.
A UITableView object maintains a queue (or list) of the currently reusable cells, each with its own reuse identifier, and makes them available to the delegate in the dequeueReusableCellWithIdentifier: method.
Did you use ARC in your project? If you did not use arc, then cell should use autorelease:
cell = [[[approveLeaveCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier] autorelease];
/* Remove all existing content from list and reload them again to avoid
* overlay of cell content */
for(UIView *view in cell.contentView.subviews){
if ([view isKindOfClass:[UIView class]]) {
[view removeFromSuperview];
}
}
// VKJ
I used the following code:
- (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];
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
if (indexPath.row == 0) {
CGRect myImageRect = CGRectMake(120.0f, 5.0f, 70.0f, 55.0f);
UIImageView *myImage = [[UIImageView alloc] initWithFrame:myImageRect];
[myImage setImage:[UIImage imageNamed:#"logo.png"]];
[cell.contentView addSubview:myImage];
}
else {
int arrayIndex = [indexPath row]-1 ;
mdict = [mmenuitems objectAtIndex:arrayIndex];
[mdict retain];
cell.textLabel.text =[mdict objectForKey:#"name"];
I got correct JSON parsed message in mmenuitems,and used indexPath.row = 0 to display a logo.
But the problem is I didn't get the last item in tableview.
Also when I scrolls the tableview the data reloads randomly and same gets repeated.
I can gusse that you need to add 1 to your number of rows method:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [mmenuitems count]+1//add 1 for the logo cell
}
So your rows count will be all the objects in the mmenuitems array + 1 cell for the logo.
But
a better way will be to add your logo to the table view header view and not to the table view rows, you can do it in your view did load after the table view is loaded:
CGRect myImageRect = CGRectMake(120.0f, 5.0f, 70.0f, 55.0f);
UIImageView *myImage = [[UIImageView alloc] initWithFrame:myImageRect];
[myImage setImage:[UIImage imageNamed:#"logo.png"]];
[self.tableView.tableHeaderView addSubview:myImage];
It will add your logo to a view on top of the first table row and won't mix in your table rows. I believe it will resolve your repetition problem.
Good luck
You could add + 1 to your numberOfRowsInSection method.
You can try using different identifiers for cells. Because the cell is being reused your contents are over written. It is not the good approach but it solves the problem nevertheless.
First of all you need to reset your cell everytime to avoid stale data
if (cell == nil) {
// cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = nil; //This clears any stale label
for(UIImageView *view in cell.contentView.subviews)
{
[view removeFromSuperView]; // This clears any subview added
}
Secondly,
Your number of rows should be
[mmenuitems count] + 1
I believe currently it is just [mmenuitems count]
I am stuck with this. I will explain with my code
- (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] autorelease];
}
NSNumber *cellno=[NSNumber numberWithUnsignedInteger:indexPath.row];
imgView = [[UIImageView alloc] initWithFrame:CGRectMake(240, 13, 15,18)];
imgView.image=[UIImage imageNamed:#"lock.png"];
tickView = [[UIImageView alloc] initWithFrame:CGRectMake(200, 13, 15,18)];
tickView.image=[UIImage imageNamed:#"tick.png"];
switch (indexPath.row) {
case 0:
cell.textLabel.text=#"apples";
if ([appDelegate.connected containsObject:cellno]) { //condition
[cell.contentView addSubview:tickView];
}else{
[cell.contentView addSubview:imgView];
}
break;
}
cell.accessoryType=UITableViewCellAccessoryDetailDisclosureButton;
return cell;
}
During the first time the tableview is loaded the 'imgView' subview is added to the cells content view and the after some operation the 'if' condition is satisfied and the 'tickView' is added.
The problem is, the oldview is not hidden or removed and hence both the images appear.
Help would be greatly appreciated
Instead of creating your imgView and tickView views in the cellForRowAtIndexPath method, create them when you create the cell and reuse them with the cell. Then you can do this:
...
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
imgView = [[UIImageView alloc] initWithFrame:CGRectMake(240, 13, 15,18)];
imgView.image=[UIImage imageNamed:#"lock.png"];
tickView = [[UIImageView alloc] initWithFrame:CGRectMake(200, 13, 15,18)];
tickView.image=[UIImage imageNamed:#"tick.png"];
}
...
if ([appDelegate.connected containsObject:cellno]) { //condition
[imgView removeFromSuperview];
[cell.contentView addSubview:tickView];
}else{
[tickView removeFromSuperview];
[cell.contentView addSubview:imgView];
}
First question on this site, although I have been around for a while behind the scenes. I have a problem that I have been racking my head on for the last two days and I hope someone can shed some light on it for me.
I have a UITableView, which is loaded from a SQL database. It has 15 entries in it. I have inserted an extra cell at the beginning of the UITableView. This extra cell is for a UITextField and UIButton which adds an item into the database.
When the view is loaded, the first cell with the custom objects shows fine, and the rest of the table is filled with items from the database and looks just how it should. However, when the UITableView is scrolled down so the first cell is out of view, then back up, it takes the value of the 11th row item and shows it over top the first cell.
Here is my code:
- (UITableViewCell *)tableView:(UITableView *)popTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
static NSInteger NameTag = 1;
UITableViewCell *cell = [popTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
CGRect frame;
frame.origin.x =50;
frame.origin.y =10;
frame.size.height =22;
frame.size.width =275;
UILabel *nameLabel = [[UILabel alloc] initWithFrame:frame];
nameLabel.tag = NameTag;
nameLabel.opaque = YES;
nameLabel.textColor = [UIColor grayColor];
nameLabel.backgroundColor = [UIColor clearColor];
[cell.contentView addSubview:nameLabel];
[nameLabel release];
}
int row = [indexPath row];
if (row == 0) {
UIButton *buttonLeft = [UIButton buttonWithType:UIButtonTypeCustom];
[buttonLeft setFrame: CGRectMake( 205, 6, 40, 33)];
[buttonLeft addTarget:self action:#selector(addToList:) forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:buttonLeft];
//No Alloc for txtField, it is built in IB
[txtField setBorderStyle:UITextBorderStyleNone];
[txtField setFrame: CGRectMake( 17, 12, 180, 23)];
txtField.backgroundColor = [UIColor clearColor];
[txtField addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
txtField.clearButtonMode = UITextFieldViewModeAlways;
}else{
UILabel * nameLabel = (UILabel *) [cell.contentView viewWithTag:NameTag];
Add *theObj = [self.theArray objectAtIndex:indexPath.row - 1];
[nameLabel setText:theObj.itemName];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
UIImageView *imageView = [cell viewWithTag:kTagCellImageView];
if (imageView == nil) {
imageView = [[UIImageView alloc]initWithFrame:CGRectMake(10.0, 10.0, 13.0, 25.0)];
imageView.backgroundColor = [UIColor clearColor];
imageView.tag = kTagCellImageView;
[cell.contentView addSubview:imageView];
}
if([theObj.itemName isEqualToString:#"First Street"]){
imageView.frame = CGRectMake(14,10,13,25);
[imageView setImage:[UIImage imageNamed:#"firststreet"]];
}
else if([theObj.itemName isEqualToString:#"Second Street"]){
imageView.frame = CGRectMake(8,12,29,20);
[imageView setImage:[UIImage imageNamed:#"second"]];
}
else if([theObj.itemName isEqualToString:#"Main Street"]){
imageView.frame = CGRectMake(15,10,13,25);
[imageView setImage:[UIImage imageNamed:#"mainstreet"]];
}
else{
imageView.frame = CGRectMake(8,8,25,25);
[imageView setImage:[UIImage imageNamed:#"iconcustom"]];
}
NSLog(#"%#",itemName);
NSLog(#"%#",itemCategory);
}
return cell;
}
Also here is my cellForRow:
- (NSInteger)tableView:(UITableView *)popTableView numberOfRowsInSection:(NSInteger)section {
return [self.theArray count] + 1; //Add Extra cell to beginning
}
Any ideas would be greatly appreciated.
You need to use a different reuseIdentifier for your first cell. Try this:
NSString *cellIdentifier;
if (indexPath.row == 0) {
cellIdentifier = #"first";
} else {
cellIdentifier = #"not first";
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
// .. cell initialization
}
Obligatory tangential answer - have you thought about setting the tableHeaderView on the UITableView instead? I think that'd accomplish what you're trying to do in a cleaner way (in that it adds an arbitrary view to the top of the table).
Just create a UIView with your "add a new item" controls in it and then set it as the header view when first creating the table.
The issue is here
static NSString *CellIdentifier = #"Cell";
static NSInteger NameTag = 1;
UITableViewCell *cell = [popTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
you are dequeueing all of the cells with the same identifier. Row 1 (index 0) needs to have its own CellIdentifier. Also it looks like you keep adding subviews to the same cells that you dequeue. On your if(cell == nil) check you may want to decide if you want to remove all of the cells contentView subviews or reuse them.
i am using the code below to implement a volume view into a cell.
[[cell detailTextLabel] setText: #""];
MPVolumeView *systemVolumeSlider = [[MPVolumeView alloc] initWithFrame: CGRectMake(100, 10, 200, 100)];
[cell addSubview: systemVolumeSlider];
[self.view addSubview:cell];
[systemVolumeSlider release];
//[MPVolumeView release];
However I have a problem with it. Whenever i scroll up or down in the tableview the MPVolumeView will be added to some other cells aswell. How could I fix this?
As mentioned in the comments, the cell with the Volume control may get re-used for non-Volume cells so it needs to be removed if it already exists. An example of how this can be done:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
}
//remove the volume control (which we tagged as 10) if it already exists...
UIView *v = [cell.contentView viewWithTag:10];
[v removeFromSuperview];
cell.textLabel.text = #"some text";
if (indexPath.section == 7)
{
if (indexPath.row == 1)
{
cell.detailTextLabel.text = #"";
MPVolumeView *systemVolumeSlider = [[MPVolumeView alloc] initWithFrame:CGRectMake(100, 10, 200, 100)];
//set a tag so we can easily find it (to remove it)...
systemVolumeSlider.tag = 10;
[cell.contentView addSubview:systemVolumeSlider];
[systemVolumeSlider release];
return cell;
}
}
cell.detailTextLabel.text = #"detail";
return cell;
}
In your comments, it seems the volume control should only be on the 2nd row of the 8th section so the example is written that way. Modify as needed.