Consistent use of UIImageView on the UITableViewCe

2019-07-05 03:33发布

问题:

I have a simple 4-tab UITabBarController, with each tab consistent of a UITableViewController. The first Tab is called Videos, the second is Languages, the third is Favourites and the fourth is Leaflets. The Videos Tab contains a list of languages (about 6) and when a cell is clicked on, a segue is performed to show the available videos of that language. The Languages tab is a list of all Languages in the app. When a cell is clicked on, the available Leaflets and Videos for that language are shown. The Favourites is populated using Core Data (I will come back to this) and finally, the Leaflets tab is a list of languages; when you click on a language, you see leaflets available in that language.

The data, content of cells, the leaflets and the videos are all populated via NSMutableArrays in the prepareForSegue. The app is working very well.

With guidance from this question: Changing the UIImage of a specific UITableViewCell when an event occurs, I am able to tap on a cell in the Languages tab and it does two things:

1) Adds a star UIImageView to the cell

2) Adds the title of that cell to Core Data

The Favourites tab is using NSFetchedResultsController to populate it's UITableViewCells with the titles of the cells that have been favourited.

That part is working really well.

Issue

However, I would now like to implement consistency. What I mean by this is, if the user selects "English" in the Languages tab and favourites a video called "3 Facts", when they go to the Videos tab and click on English, the "3 Facts" cell should have a favourite on it.

The Languages tab is the only UITableViewController that after showing the Languages, shows a UITableViewController with sections with Leaflets on section 0 and Videos on section 1. If the user goes to the Videos tab and selects a Language, it only contains one section.

This is the code that is currently doing the favouriting:

- (void)swipeableTableViewCell:(SWTableViewCell *)cell didTriggerRightUtilityButtonWithIndex:(NSInteger)index
{
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
    CustomLeafletVideoTableViewCell *selectedCell = (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 = selectedCell.customCellLabel.text;

    NSLog(@"The text is %@", cellTitle);
    NSManagedObjectContext *context = [self managedObjectContext];
    NSString *key = [NSString stringWithFormat:@"%@_%ld_%ld", self.selectedLanguage, (long)indexPath.section, (long)indexPath.row];
    if (self.favoritesDict[key] == nil)
    {
        self.favoritesDict[key] = @(1);
        Favourites *favourites = [NSEntityDescription insertNewObjectForEntityForName:@"Favourites" inManagedObjectContext:context];
        favourites.title = cellTitle;

    }
    else
    {

        [self.favoritesDict removeObjectForKey:key];
    }

    [[NSUserDefaults standardUserDefaults] setObject:self.favoritesDict forKey:@"favoritesDict"];
    NSError *error = nil;
    if (![context save:&error])
    {
        // Error
    }
    [cell hideUtilityButtonsAnimated:YES];

    [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];

}

The viewDidLoad and viewWillAppear contains:

if ([[NSUserDefaults standardUserDefaults] valueForKey:@"favoritesDict"] == nil) {
    [[NSUserDefaults standardUserDefaults] setObject:@{} forKey:@"favoritesDict"];
}

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

The cellForRowAtIndexPath contains:

if(indexPath.section==0)
{
    customCell.customCellLabel.text = [NSString stringWithFormat:@"%@",[self.availableLeaflets objectAtIndex:indexPath.row]];
    NSString *key = [NSString stringWithFormat:@"%@_%ld_%ld", self.selectedLanguage, (long)indexPath.section, (long)indexPath.row];
    if (self.favoritesDict[key]) {
        // show the favorite image
        customCell.customCellImage.hidden = NO;
    } else {
        // hide the favorite image
        customCell.customCellImage.hidden = YES;
    }
}
else
{
    customCell.customCellLabel.frame = CGRectMake(8, 20, 100, 40);
    customCell.customCellLabel.text = [NSString stringWithFormat:@"%@",[self.availableVideos objectAtIndex:indexPath.row]];

    NSString *key = [NSString stringWithFormat:@"%@_%ld_%ld", self.selectedLanguage, (long)indexPath.section, (long)indexPath.row];
    if (self.favoritesDict[key]) {
        // show the favorite image
        customCell.customCellImage.hidden = NO;
    } else {
        // hide the favorite image
        customCell.customCellImage.hidden = YES;
    }

}

The NSString *key has a role to play here because it is obtaining the correct section and row. When I copy this code over to the Videos tab, the favourite does not exist on the same title that it does with the Languages tab.

Ultimately, consistency is the important thing here. The user may favourite something from the Videos tab or Languages tab, but either way, the same "title" should be favourited in the other tab.

Update

Based on the comment of using NSUserDefaults, I have added some code. Firstly, in the LanguagesTab, I have added some code in the method that does the favouriting:

NSString *key = [NSString stringWithFormat:@"%@_%ld_%ld", self.selectedLanguage, (long)indexPath.section, (long)indexPath.row];
if (self.favoritesDict[key] == nil)
{
    self.favoritesDict[key] = @(1);
    Favourites *favourites = [NSEntityDescription insertNewObjectForEntityForName:@"Favourites" inManagedObjectContext:context];
    favourites.title = cellTitle;


    NSString *valueToSave = cellTitle;
    NSLog(@"The valuetosave is %@", cellTitle);
    [[NSUserDefaults standardUserDefaults] setObject:valueToSave forKey:@"starredName"];
    [[NSUserDefaults standardUserDefaults] synchronize];


}

Back in the VideosTab, in the cellForRow, I have:

NSString *key = [NSString stringWithFormat:@"%@_%ld_%ld", self.selectedLanguage, (long)indexPath.section, (long)indexPath.row];
if (self.favoritesDict[key]) {
    // show the favorite image
    customCell.customCellImage.hidden = NO;
} else {
    // hide the favorite image
    customCell.customCellImage.hidden = YES;
}

NSString *savedValue = [[NSUserDefaults standardUserDefaults]
                        stringForKey:@"starredName"];

if ([savedValue isEqualToString:@"# 3 The One Show"])
{
    NSLog(@"Display star");
    customCell.customCellImage.hidden = NO;

}
else
{
    NSLog(@"Don't display star"); 
}

This works to some extent. For example, I selected a cell in the Languages tab called # 3 The One Show and when I come back to the Videos tab, it does detect that in the if statement and it runs the NSLog to display a star. It then displays the star. However, the issue is, it shows the star on EVERY cell. I want it to only show a star on the cell that has the text "# 3 The One Show".

I tried:

NSString *savedValue = [[NSUserDefaults standardUserDefaults]
                        stringForKey:@"starredName"];

if ([savedValue isEqualToString:@"# 3 The One Show"])
{
    if ([customCell.customCellLabel.text isEqualToString:@"# 3 The One Show"])
    {
        NSLog(@"Display star");
        customCell.customCellImage.hidden = NO;

    }

}
else
{
    NSLog(@"Don't display star"); 
}

This looks like it's working and now showing and not-showing the cell. However, this works with 1 value in the savedValue. In the cellForRow, if I have:

NSString *savedValue = [[NSUserDefaults standardUserDefaults]
                        stringForKey:@"starredName"];

if ([savedValue isEqualToString:@"# 3 The One Show"])
{
    NSLog(@"Display star");
    NSLog(@"The cell is %@", customCell.customCellLabel.text);
    if ([customCell.customCellLabel.text isEqualToString:@"# 3 The One Show"])
    {
        customCell.customCellImage.hidden = NO;

    }

}
else if ([savedValue isEqualToString:@"Real Talk - Sangat TV discussion #TruthAbout1984"])
{
    NSLog(@"Display the star yo");
    NSLog(@"The title is %@", customCell.customCellLabel.text);
    if ([customCell.customCellLabel.text isEqualToString:@"Real Talk - TV discussion"])
    {
        customCell.customCellImage.hidden = NO;
    }
}
else
{
    NSLog(@"Don't display star"); 
}

It only shows the star on the latest entry to the savedValue NSUserDefaults and because I have 1000+ entries, it won't be efficient to actually create different keys for each different entry, etc.

Now, because my Favourites UITableViewController is being populated by Core Data and the UITableViewCells are being populated by favourites.title, could I do something with that? So, I already have the values of the titles that have been favourited, but isn't there a way to translate that in the Videos tab. Perhaps do a fetch request to get the titles, etc? I just need some guidance with this.

I have this code:

Favourites *favourite = nil;

NSManagedObjectContext *context = [self managedObjectContext];

NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Favourites"];
request.predicate = [NSPredicate predicateWithFormat:@"title != nil"];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"title" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];

NSError *error = nil;
NSArray *favs = [context executeFetchRequest:request error:&error];


if (!favs)
{
    NSLog(@"Nothing to see here");
    // Handle Error
}
else
{
    // If the object exists, just return it
    //        favourite = [favs lastObject];

    NSLog(@"Number of objects %lu", [favs count]);


    NSString *elements;
    for (elements in favs)
    {

        NSLog(@"Elements %@", elements);
    }
    NSLog(@"Things to see here");
}

NSLog(@"The Favourites are %@", favourite.title);

This is more just stabbing in the dark though - I'm not sure how to return all of the objects of the Array and then to place the image on that cell with customCell.customCellImage.hidden = NO, etc.

Any guidance on this would be really appreciated.