我的 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 传递到 UIImage
TableViewCell.xib 没有出现在 tableview 上