简体   繁体   中英

Changing the UIImage of a specific UITableViewCell when an event occurs

I have a simple UITableViewController with some static cells in the UITableView . The UITableView is being populated by another UITableViewController 's prepareForSegue . There are two sections to this UITableViewController , where the first section is a NSMutableArray of strings and the second section is a NSMutableArray containing a .txt file with strings. Some "languages" will only have one section and others will have two. There's nothing else fancy about the UITableView . With the use of this tutorial: http://www.appcoda.com/swipeable-uitableviewcell-tutorial/#disqus_thread , I have managed to implement custom gestures on the cell, so I can swipe the cell to mark it as favourite. I had to implement the use of the code in that tutorial to change the default behaviour from Delete to Star, as can be seen in the screenshot below:

在此处输入图片说明

Once a user has selected the star image, I want there to be UIImage on the cell itself, representing that this cell has been starred.

Here's some code, starting with the cellForRowAtIndexPath

static NSString *strCellIdentifier = @"CustomLeafletVideoCell";
CustomLeafletVideoTableViewCell *customCell = (CustomLeafletVideoTableViewCell *)[tableView dequeueReusableCellWithIdentifier:strCellIdentifier];

self.rightUtilityButton = [NSMutableArray new];

if (![[NSUserDefaults standardUserDefaults] boolForKey:@"Favourite"])
{
    [self.rightUtilityButton sw_addUtilityButtonWithColor:
     [UIColor colorWithRed:1.0f green:0.0f blue:0.0f alpha:1.0]
                                                 icon:[UIImage imageNamed:@"Favorites@2x.png"]];

}
else if ([[NSUserDefaults standardUserDefaults] boolForKey:@"Favourite"])
{
    [self.rightUtilityButton sw_addUtilityButtonWithColor:
     [UIColor colorWithRed:1.0f green:0.0f blue:0.0f alpha:1.0]
                                                 icon:[UIImage imageNamed:@"Database@2x.png"]];


}

customCell.rightUtilityButtons = self.rightUtilityButton;
customCell.delegate = self;

When the user taps the image in the cell, this method fires off:

- (void)swipeableTableViewCell:(SWTableViewCell *)cell didTriggerRightUtilityButtonWithIndex:(NSInteger)index
{

    switch (index) {
        case 0:
        {

        self.selectedRowCollection = [[NSMutableDictionary alloc] init];


        NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];

        CustomLeafletVideoTableViewCell *cell = (CustomLeafletVideoTableViewCell*)[self.tableView cellForRowAtIndexPath:indexPath];

        // We create a new NSString and assign it to the custom label's text (which is obtained from the cellForRow method)
        NSString *cellTitle = cell.customCellLabel.text;

        NSLog(@"The text is %@", cellTitle);


        NSManagedObjectContext *context = [self managedObjectContext];

        Favourites *favourites = [NSEntityDescription insertNewObjectForEntityForName:@"Favourites" inManagedObjectContext:context];
        favourites.title = cellTitle;

        NSError *error = nil;
        if (![context save:&error])
        {
            // Error
        }


        [cell hideUtilityButtonsAnimated:YES];


        [self.tableView reloadData];
    }
}

I am storing the "title" in Core Data.

Issue

When I swipe the cell and press the star image, it doesn't load up the cell with the UIImageView in the designated area. The reason it doesn't is because I truly don't understand what to do.

I understand the answer is indicating that I should create a custom class and while I understand the theory behind that, I cannot understand how to actually implement this appropriately.

I've looked at this reference: Using BOOL objects in NSMutableArray to determine cell statuses to use a checkmark as the accessory when a cell is selected. This works, but it places a checkmark in the first section and second section on the same corresponding cell.

I've figured out I can get the exact row number and section number from indexPath.row and indexPath.section , but I'm just not sure how to tackle this information at all. I could always add a isFavourite BOOL to the Core Data Model, but how do I actually set that in the cellForRowAtIndexPath?

So to conclude, and for the 250 bounty I'm putting on this question, I need to understand how:

  • Set the specific indexPath.row and indexPath.section with the image, and
  • Maintain it so that every time I come back to this UITableViewController , the star is on the appropriate cell

I'm kind of a newbie here, so if you're happy to help with as much information as you can, I'd really appreciate that.

Also, I'm not having issues with what to do with the Favourite after; that works - I just need to get the image onto the cell when a cell has been marked as favourite.

Any guidance would be appreciated.

Update

This is the code I have for setting the favourites:

        self.isFavourite = @(!self.isFavourite.boolValue);

Where self.isFavourite is a NSNumber property created on this UITableViewController .

In the cellForRowAtIndexPath :

    customCell.customCellLabel.text = [NSString stringWithFormat:@"%@",[self.availableLeaflets objectAtIndex:indexPath.row]];
    if (self.isFavourite.boolValue)
    {
        customCell.accessoryType = UITableViewCellAccessoryCheckmark;
    }
    else
    {
        customCell.accessoryType = UITableViewCellAccessoryNone;
    }

The code here is setting the titles from the self.availableLeaflets . This works to set the checkmark on the cell, but the problem is, when I come back to this UITableViewController , the checkmark hasn't persisted on the selected cell.

Here, self.availableLeaflets is a NSMutableArray that gets populated and set from the prepareForSegue in the previous UITableViewController .

Your code marks all cells as favorite when a user taps on the star in one cell because you store only 1 key in the UserDefaults.

You have to store the favorite state for each cell individually. Each cell must have its own 'favorite' boolean value.

Update:

This is a working example on how to achieve want you want without using Core Data. I simplified the example for clarity reasons:

  1. The tableview shows the title of the cell. If a cell is a favorite, it shows the checkmark accessory view.
  2. To mark a cell you simply select it. (I ommitted the whole button code the keep the example simple). If you select the cell a second time it is removed from the favorites

Here's what you have to do:

#import "ViewController.h"
#import <CoreData/CoreData.h>
#import "CellData.h"
#import "AppDelegate.h"

@interface ViewController () <UITableViewDataSource, UITableViewDelegate>
@property (nonatomic) UITableView *tableView;
@property (nonatomic) NSMutableDictionary *favoritesDict;
@property (nonatomic) NSInteger context;
@property (nonatomic) NSString *language;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // setup the table view
    self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
    self.tableView.dataSource = self;
    self.tableView.delegate = self;
    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];
    [self.view addSubview:self.tableView];

    // setup the favorites dictionary in user defaults (if it does not exist)
    if ([[NSUserDefaults standardUserDefaults] valueForKey:@"favoritesDict"] == nil) {
        [[NSUserDefaults standardUserDefaults] setObject:@{} forKey:@"favoritesDict"];
    }

    // set the language of your current table view
    self.language = @"en";

    // load favorites from user defaults
    self.favoritesDict = [[[NSUserDefaults standardUserDefaults] valueForKey:@"favoritesDict"] mutableCopy];

}

// this method changes the favorite state of the cell at a given index path
- (void)toggleFavoriteStateForCellAtIndexPath:(NSIndexPath *)indexPath {

    // toggle the favorite state of the cell
    NSString *key = [NSString stringWithFormat:@"%@_%ld_%ld", self.language, (long)indexPath.section, (long)indexPath.row];
    if (self.favoritesDict[key] == nil) {
        self.favoritesDict[key] = @(1);
    } else {
        [self.favoritesDict removeObjectForKey:key];
    }

    // save the change
    [[NSUserDefaults standardUserDefaults] setObject:self.favoritesDict forKey:@"favoritesDict"];

    // reload the cell
    [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}

#pragma mark - UITableViewDataSource

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 2;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 10;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

    // add the text to your cell

    // set up favorite state
    NSString *key = [NSString stringWithFormat:@"%@_%ld_%ld", self.language, (long)indexPath.section, (long)indexPath.row];
    if (self.favoritesDict[key]) {
        // show the favorite image
        cell.accessoryType = UITableViewCellAccessoryCheckmark; // for this example: show checkmark
    } else {
        // hide the favorite image
        cell.accessoryType = UITableViewCellAccessoryNone; // for this example: hide checkmark
    }

    return cell;
}

#pragma mark - UITableViewDelegate

// toggle the favorite state of the cell when the user selects it
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    [self toggleFavoriteStateForCellAtIndexPath:indexPath];
}

@end

This example works for tables with multiple sections. It uses a NSDictionary and stores favorited cells in a key that has the following syntax LANGUAGE_SECTION_ROW . To check if a cell is marked as favorite just check if there is a object for the related key in the dictionary. The actual value of that key does not matter. You just check for the key.

Just make sure that you set the language string in viewDidLoad .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM