我的 TableViewCell 没有从核心数据中删除,当 tableview 重新出现时重新出现

Posted

技术标签:

【中文标题】我的 TableViewCell 没有从核心数据中删除,当 tableview 重新出现时重新出现【英文标题】:My TableViewCell isn't deleting from Core Data, reappears when tableview is brought back into view 【发布时间】:2017-04-21 19:21:56 【问题描述】:

我有一个 CoreDataManager 类,它负责创建要在 TableView 中显示的代码和描述,还负责向 Tableview 添加其他行以保留在 Core Data 中。当我添加新行时,它们会完全按照应有的方式出现在 Tableview 中,当我滑动删除它们时,它们会按原样消失,但是当我离开 TableView 并返回时,我刚刚删除的行仍然存在。我将发布一些CoreDataManager 类和TableView 类。

CoreDataManager.h -

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@interface CoreDataManager : NSObject

@property (readonly, strong) NSPersistentContainer *persistentContainer;

- (void)saveContext;

-(BOOL)deleteCode:(NSString*)name description:(NSString*)desc;

+(CoreDataManager*)sharedInstance;

-(void)storeListFirstTime; //This will save your initial list of content

-(NSArray*)fetchAllRecords;//get All the record from your table

-(BOOL)saveNewCode:(NSString*)codeName description:(NSString*)codeDesc;

@end 

CoreDataManager.m -

#import "CoreDataManager.h"
#import "UsefulCodes+CoreDataClass.h"

@implementation CoreDataManager

+(CoreDataManager*)sharedInstance 
    static CoreDataManager *sharedObject;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^
        sharedObject = [[CoreDataManager alloc] init];
    );

    return sharedObject;


//THIS HOLDS ALL THE INITIAL CODES AND DESCRIPTIONS IN TABLEVIEW AND ARE NOT TO BE REMOVED
-(void)storeListFirstTime 

    NSArray* presetList = [NSArray arrayWithObjects:@"AS",
                                               @"BCNU",
                                               @"CL",
                                               @"CT",
                                               @"CUL",
                                               @"K",
                                               @"QSL",
                                               @"QSL?",
                                               @"QRX?",
                                               @"QRV",
                                               @"QRV?",
                                               @"QTH",
                                               @"QTH?",
                                               @"R",
                                               @"SN",
                                               @"SOS",
                                               @"73",
                                               @"88",
                                               nil];


    NSArray* codeDescArray = [NSArray arrayWithObjects:@"Wait",
                                                  @"Be seeing You",
                                                  @"Going off air",
                                                  @"Start Copying",
                                                  @"See you later",
                                                  @"Over",
                                                  @"I acknowledge receipt",
                                                  @"Do you acknowledge",
                                                  @"Should I wait",
                                                  @"Ready to copy",
                                                  @"Are you ready to copy?",
                                                  @"My location is ...",
                                                  @"What is your location?",
                                                  @"Roger",
                                                  @"Understood",
                                                  @"Distress message",
                                                  @"Best regards",
                                                  @"Love and kisses",
                                                  nil];

//Saves the initial list of items
for(int i = 0; i < presetList.count; i++) 
        NSManagedObjectContext *context = [self context];
        UsefulCodes *codeObj = [NSEntityDescription insertNewObjectForEntityForName:@"UsefulCodes"
                                                           inManagedObjectContext:context];
        codeObj.codeName = [presetList objectAtIndex:i];
        codeObj.codeDescription = [codeDescArray objectAtIndex:i];
    
    [self saveContext];


-(NSArray*)fetchAllRecords 

    NSManagedObjectContext *context = [self context];
    NSError *error = nil;
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"UsefulCodes"];
    NSArray *records = [context executeFetchRequest:request
                                          error:&error];

    if(error == nil && records.count > 0) 
        return [records copy];
    
    else 
        //Handle error by returning new array
        return [NSArray new];
    


//RESPONSIBLE FOR SAVING NEW CODE AND ADDING TO TABLEVIEW

-(BOOL)saveNewCode:(NSString*)codeName description:(NSString*)codeDesc 

    NSManagedObjectContext *context = [self context];
    NSError *error = nil;
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"UsefulCodes"];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"codeName = %@", codeName];
    request.predicate = predicate;

    NSArray *records = [context executeFetchRequest:request
                                          error:&error];

    if(error == nil && records.count > 0) 
        UsefulCodes *code = [records firstObject];

        //Updating description
        code.codeDescription = codeDesc;
    
    else //Add new code Object to table
        NSManagedObjectContext *context = [self context];
        UsefulCodes *codeObj = [NSEntityDescription insertNewObjectForEntityForName:@"UsefulCodes"
                                                          inManagedObjectContext:context];
        codeObj.codeName = codeName;
        codeObj.codeDescription = codeDesc;
    

    //Save changes
    if ([context hasChanges] && ![context save:&error]) 
        //Saved successfully
        return true;
    
    else 
        //handle error
        return false;
    

    return true;


/*  Boiler plate Core Data Stack set up done here  */

#pragma mark - Core Data Saving support

- (void)saveContext 
    NSManagedObjectContext *context = self.persistentContainer.viewContext;
    NSError *error = nil;
    if ([context hasChanges] && ![context save:&error]) 
        NSLog(@"Unresolved error %@, %@", error, error.userInfo);
    


-(NSManagedObjectContext*)context 
    return self.persistentContainer.viewContext;


@end

我相信“fetchAllRecords”方法是 tableview 再次返回已删除对象的罪魁祸首,正如您将在下面的 TableViewController 类中看到的那样。

MCTableViewController.h -

@interface MCTableViewController :     UITableViewController<addNewCellData> 
    __weak id selectDataDelegate;
    //CUSTOM DELEGATE RESPONSIBLE FOR HANDLING NEW CODE AND DESCRIPTION INPUT AND PASSING INTO TABLEVIEW


@property (readonly, strong) NSPersistentContainer *persistentContainer;
@property(strong,nonatomic)NSMutableArray *presetList;
@property(strong,nonatomic)NSMutableArray *codeDescArray;
@property(nonatomic,weak)id<sendDataProtocol> selectedDataDelegate;
@property(strong,nonatomic)UILabel *codeTitle;
@property(strong,nonatomic)UILabel *codeDesc;

MCTableViewController.m -

- (void)viewDidLoad 
    [super viewDidLoad];

    //Declare new NSMutableArray in the two properties below
    self.presetList = [NSMutableArray new];
    self.codeDescArray = [NSMutableArray new];

    //Loading data from DB
    [self reloadDataset];


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
    return [self.presetList count];


//THIS IS WHERE EDITING HAPPENS AND WHERE I'M TRYING TO REMOVE THE CORE DATA OBJECT FROM THE TABLEVIEW

-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
    if (editingStyle == UITableViewCellEditingStyleDelete) 

        NSManagedObject *selectedObject = [self.presetList objectAtIndex:[indexPath row]];
        [self.context deleteObject:selectedObject];
        [self.context save:nil];

        [self.presetList removeObjectAtIndex:[indexPath row]];
        [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationFade];
    


//DATA IS RECEIVED FROM OTHER VIEW HERE AND SAVED TO THE TABLEVIEW
#pragma mark - Delegate for receiving new data
- (void)sendDataToTableView:(NSString*)code codeDesc:(NSString*)desc 

    NSString *codes = code;
    NSString *descriptions = desc;

    [self.presetList addObject:codes];
    [self.codeDescArray addObject:descriptions];

    //Adding new record OR
    //If codeName is same, updating description in database
    [[CoreDataManager sharedInstance] saveNewCode:codes description:descriptions]; 

    [self reloadDataset];


//FINALLY...

#pragma mark - Reloading table data from database
-(void)reloadDataset 

    NSArray *array = [[CoreDataManager sharedInstance] fetchAllRecords];

    //Removing all objects from current list
    [self.presetList removeAllObjects];
    [self.codeDescArray removeAllObjects];

    for (UsefulCodes *code in array) 

        //CODENAME & CODEDESCRIPTION ARE ATTRIBUTES OF MY CORE DATA ENTITY USEFULCODES
        [self.presetList addObject: code.codeName];
        [self.codeDescArray addObject: code.codeDescription];
    

    [self.tableView reloadData];

将这些新对象添加到 tableview 并将这些新对象保存到核心数据很简单,但删除它们一直具有挑战性,我已经尝试了很多但我无法让它工作。如果您已经做到了这一点,我将不胜感激关于我做错了什么以及为什么数据没有从 Core Data 中正确删除的一些建议。

【问题讨论】:

看起来就像你试图删除错误的东西。您的代码NSManagedObject *selectedObject = [self.presetList objectAtIndex:[indexPath row]]; 可能 中的这一行不会返回实际的托管对象,因为当您使用reloadDataset 时,您使用code.codeName 填充presetList。在那里放一个断点,看看selectedObject是否真的是一个有效的对象。 【参考方案1】:

这一切都不起作用的原因是我需要访问整个存储的项目列表,然后选择我想要删除的特定索引。为了获得存储项目的完整列表,我必须调用我创建的单例并获取“fetchAllRecords”方法,然后将其存储在数组中,然后像往常一样继续删除对象。总体而言,代码非常简单,我将在下面发布我自己的问题的答案。

-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 

         if (editingStyle == UITableViewCellEditingStyleDelete) 

            //GET ALL THE CELLS CURRENTLY STORED
            NSArray *array = [[CoreDataManager sharedInstance] fetchAllRecords];
            //GET THE SPECIFIC INDEX OF THE STORED ARRAYS
            NSManagedObject *selectedObject = [array objectAtIndex:[indexPath row]];
            [selectedObject.managedObjectContext deleteObject:selectedObject];
            NSError *saveError;
            [selectedObject.managedObjectContext save:&saveError];

            [self.presetList removeObjectAtIndex:[indexPath row]];
            [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationFade];
        
    

【讨论】:

以上是关于我的 TableViewCell 没有从核心数据中删除,当 tableview 重新出现时重新出现的主要内容,如果未能解决你的问题,请参考以下文章

如何从 TableViewCell 推送新视图?

如何将图像从 TableViewCell 传递到 UIImage

TableViewCell.xib 没有出现在 tableview 上

从 tableviewcell 获取单元格索引

从 `ViewWillAppear` 触发 `TableViewCell` 函数

从`ViewWillAppear`触发`TableViewCell`函数