Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Thelle93

macrumors newbie
Original poster
Oct 7, 2012
18
0
I wan't to implement a favorited section on my iOS app in my tableview. So if i click on a left detail image on a row, it should go up to a "Favorites" section and still be showing in the standard section. and the same by removing it in favorites. Like this:

screen568x568.jpeg

Please give me some hints! :)
Thanks in advance
 
I am not going to write it for you, but you could try having two arrays. One for favorites, one for regular items. Setup your table view controller to pull from a certain array based on the section property of the table view cell indexPath. If an item in your section # 2 is selected, add it to the favorites array and reload the data. You should be able to figure out the rest from there
 
Basically you’re going to setup sections in your UITableView, there’s a ton of tutorials online, and a bunch of built-in methods to handle this (numberOfSectionsInTableView, titleForHeaderInSection). In short: you define the number of sections (2 in your case, though this is easily done dynamically as well), apply titles, then handle allocation of each data member to the section during the view generation (i.e., in cellForRowAtIndexPath).

You’re going to want to have a construct to handle this, something like an array with arrays/dictionaries that are allocated to the proper key based on the section target. Then some basic use of didSelectRowAtIndexPath to determine the tap, assign (or deassign) the cell data to the favorites section, refresh your datasource.

Should all be pretty standard UITV patterns, good luck :)
 
Yes I have aldready Done that, i have one array with the standard rows and then another one that is empty. I have two sections with headers and the top one is empty because favorites array is empty. In the table view the original array is loaded into the cellidentifier.

Should I have another cellidentifier for the favorited rows?
And use the method moveRowAtIndexPath?
This is where I'm stuck, moving the row to the first section when it gets tapped on the image.
Thanks again:)
 
Yes I have aldready Done that, i have one array with the standard rows and then another one that is empty. I have two sections with headers and the top one is empty because favorites array is empty. In the table view the original array is loaded into the cellidentifier.
If you're already that far along, providing us some of your code might help.

Should I have another cellidentifier for the favorited rows?
I would suggest: no, not unless those cells have a different layout.

And use the method moveRowAtIndexPath?
This is where I'm stuck, moving the row to the first section when it gets tapped on the image.

Based on this requirement from your first post, it doesn't sound like you want to move the row at all, but duplicate it into the Favorites section:
So if i click on a left detail image on a row, it should go up to a "Favorites" section and still be showing in the standard section.

What does your tableView:didSelectRowAtIndexPath: method look like?
 
Yes you are I just wan't to duplicate them. okay here is some relevant code.

Code:
- 
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *segueRow = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    segueRow.textLabel.text=self.objects[indexPath.row];

    //Conditionally perform segues, here is an example:
    if ([segueRow.textLabel.text isEqualToString:@"xxx"] )
    {
        [self performSegueWithIdentifier:@"xxx" sender:self];
    }
    else if .........
    }
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   
    
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if(cell)
        cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    cell.textLabel.text=self.objects[indexPath.row];
    cell.detailTextLabel.text =self.subtitles[indexPath.row];
    cell.detailTextLabel.textColor=[UIColor lightGrayColor];
    
    
    // left image
    UIImageView *image=[[UIImageView alloc] initWithFrame:CGRectMake(7, 7, 30, 30)];
    [image.layer setCornerRadius:image.frame.size.width/2];
    [image setClipsToBounds:YES];
     image.image=[UIImage imageNamed:[self.icons objectAtIndex:indexPath.row]];
    [cell.contentView addSubview:image];
    
    //Favorites
    cell.imageView.userInteractionEnabled = YES;
    cell.imageView.tag = indexPath.row;
    UITapGestureRecognizer *tapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(addToFavs:)];
    tapped.numberOfTapsRequired = 1;
    [cell.imageView addGestureRecognizer:tapped];

    return cell;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    
    if(section==0)return [self.favs count];
    else return [self.objects count]; 
}

-(void)addToFavs:(id)sender{
    UITapGestureRecognizer *gesture = (UITapGestureRecognizer *) sender;
    NSLog(@"Tag = %d", gesture.view.tag);   
}

"objects", "subtitles" and "icons" is the titles, subtitles and left image arrays. And "favs" is the empty array.

As you see at he bottom I have an IBAction to get the tag of the tap, but it doesn't recognize it because the image is in a contentView... If I change it to recognize the contentView it works but then I can tap all over the cell and thats not how it's suppose to be.
 
So, the real concern is not "how can I write code to achieve this functionality" but rather "why doesn't the code I already wrote achieve this functionality". Ah. I would suggest trying to be as explicit as possible in your queries so that we better understand what you're asking. Maybe have a read through this excellent article from Mike Ash: Getting Answers.

On to the actual issue: You seem to be adding a UIImageView to your contentView, but then add the gesture recognizer to the cell's built-in imageView. I doubt that's what you really want.

Plus, you don't need to be doing these things every time cellForRowAtIndexPath: is called. I would suggest moving most of that code into the "if(cell)" block.
 
Well I have different images to each row, and i'm modifying the image. So I have to add it in the contentView, right? I know that code is wrong, that's why I didn't provide it from the beginning. But I think I can fix that problem by my self.

I just need to figure out how to duplicate the rows into section=0 when the imageView is tapped. Then when tapped again back to section=1. I know it's simple but I can't find anything related on google. Sorry if I'm unclear in this thread, I am a completely newbie in ios development.

Thanks again.
 
Well I have different images to each row, and i'm modifying the image. So I have to add it in the contentView, right?

No. The cell already has an imageView, as your UITapGestureRecognizer addition shows. Why add another one?

I just need to figure out how to duplicate the rows into section=0 when the imageView is tapped. Then when tapped again back to section=1.

Don't get ahead of yourself yet. Apply some basic debugging principles. I think you need to figure out why the gesture method is not getting triggered. Fix that first. Then you can worry about adding to the favorites.
 
Well I have different images to each row, and i'm modifying the image. So I have to add it in the contentView, right? I know that code is wrong, that's why I didn't provide it from the beginning. But I think I can fix that problem by my self.

I just need to figure out how to duplicate the rows into section=0 when the imageView is tapped. Then when tapped again back to section=1. I know it's simple but I can't find anything related on google. Sorry if I'm unclear in this thread, I am a completely newbie in ios development.

Thanks again.

No, you don't understand what Dojo is telling you.

A cell gets created once, and then reused many times. The logic for cellForRowAtIndexPath should be:

Code:
cell = dequeue old cell.
if (!cell)
{
   cell = alloc a new cell
   add custom fields to cell
}

now fully configure all cell fields, including installing text and images


The only time you should add fields to a cell is if you get back nil from the dequeue call, and need to create a new cell. If you DO get back a recycled cell, it will already have the fields you need.

Note that you can also set up cell prototypes if you're using starboards. That's a cleaner, more modern way to do things.
 
No. The cell already has an imageView, as your UITapGestureRecognizer addition shows. Why add another one?



Don't get ahead of yourself yet. Apply some basic debugging principles. I think you need to figure out why the gesture method is not getting triggered. Fix that first. Then you can worry about adding to the favorites.

Now it's working. I now have a "star" image as the accessoryView and the tags are working!

Code:
//fav image
        UIImageView *fav = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"favorites.png"]];
        cell.accessoryView = fav;
        [fav setFrame:CGRectMake(0, 0, 25, 25)];
        [fav setClipsToBounds:YES];
        if(!indexPath.section==0) {
            fav.image=[UIImage imageNamed:@"unfavorites"];
        }
        //Favorites
        cell.accessoryView.userInteractionEnabled = YES;
        cell.accessoryView.tag = indexPath.row;
        UITapGestureRecognizer *tapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(addToFavs:)];
        tapped.numberOfTapsRequired = 1;
        [cell.accessoryView addGestureRecognizer:tapped];

So now I can move on...
 
Last edited:
I got it sort of working, but only the textLabel gets in to that section at the right row, both the subtitle and left-image doesn't get to the right index. So I guess I have to create two more arrays for the subtitle and left image too, and do the same with them?... Or is there a better way?

Code:
-(void)addToFavs:(id)sender{
    UITapGestureRecognizer *gesture = (UITapGestureRecognizer *) sender;
    NSLog(@"Tag = %d", gesture.view.tag);
    [self.favs addObject:[self.objects objectAtIndex:gesture.view.tag]];
    [self.tableView reloadData];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    
    
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell){
        cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    }
    //cell.detailTextLabel.textColor=[UIColor lightGrayColor];
    cell.textLabel.text=self.objects[indexPath.row];
    cell.detailTextLabel.text =self.subtitles[indexPath.row];
    
    
    // left image
    UIImageView *image=[[UIImageView alloc] initWithFrame:CGRectMake(7, 7, 30, 30)];
    [image.layer setCornerRadius:image.frame.size.width/2];
    [image setClipsToBounds:YES];
    [image.layer setBorderColor:[UIColor lightGrayColor].CGColor];
    [image.layer setBorderWidth:0.3f];
    image.image=[UIImage imageNamed:[self.icons objectAtIndex:indexPath.row]]; 
    
    //fav image
    UIImageView *fav = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"favorites.png"]];
    cell.accessoryView = fav;
    [fav setFrame:CGRectMake(0, 0, 25, 25)];
    [fav setClipsToBounds:YES];
    if(!indexPath.section==0) {
        fav.image=[UIImage imageNamed:@"unfavorites"];
    }
    //Favorites
    cell.accessoryView.userInteractionEnabled = YES;
    cell.accessoryView.tag = indexPath.row;
    UITapGestureRecognizer *tapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(addToFavs:)];
    tapped.numberOfTapsRequired = 1;
    [cell.accessoryView addGestureRecognizer:tapped];
    
    //favorites content
    if (indexPath.section == 0)
    {
        cell.textLabel.text=self.favs[indexPath.row];
        [cell.contentView addSubview:image];
        cell.detailTextLabel.text =self.subtitles[indexPath.row];
    }
    else if (indexPath.section == 1)
    {
        cell.textLabel.text=self.objects[indexPath.row];
        [cell.contentView addSubview:image];
    }
    
    return cell;
}
 
I would suggest storing your data for the table either in an array of dictionaries or, better yet, create a custom class to hold the data for each row. Then, because you should reference instances via a pointer, you can simply add and remove those objects from your favorites array.

Also, you still haven't moved a bunch of code into your "if (cell)" block. That can cause performance issues and doesn't take advantage of cell reuse.
 
I would suggest storing your data for the table either in an array of dictionaries or, better yet, create a custom class to hold the data for each row. Then, because you should reference instances via a pointer, you can simply add and remove those objects from your favorites array.

Also, you still haven't moved a bunch of code into your "if (cell)" block. That can cause performance issues and doesn't take advantage of cell reuse.

Okay that's seems complicated... I thought this task should be simple, to just copy the cells into the first section.:p I think I will do as i said in the previous post and save the array with NSUserDefaults. cause it works:) And then add some method to remove them from the array if I tap the image again.

But one thing, when I'm tapping the image and the row is added to the section, it just pops up with no animation, how can I fix that?

About the if (cell) block I just moved most of the code in there now:)

Thanks again.
 
Okay that's seems complicated... I thought this task should be simple, to just copy the cells into the first section.:p I think I will do as i said in the previous post and save the array with NSUserDefaults. cause it works:) And then add some method to remove them from the array if I tap the image again.

Frequently, a task you think is simple will turn out not to be. And although a quick-and-dirty solution may be tempting, in the long run, you're better off stepping back a bit and designing a better, more-scaleable, easier-to-debug solution. It'll take more time but, usually, it's worth it.

But one thing, when I'm tapping the image and the row is added to the section, it just pops up with no animation, how can I fix that?

Take advantage of a UITableView's animated reloading methods. I would suggest reading through the entire Table View Programming Guide for iOS, just so you know everything that it is capable of.
 
Take advantage of a UITableView's animated reloading methods. I would suggest reading through the entire Table View Programming Guide for iOS, just so you know everything that it is capable of.

Yeah I found this code:
Code:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
But the problem is that I'm adding a new string to the array, not really inserting a new row to the tableview, or am I wrong?
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.