从 UIViewController 中的 UITableView 中删除核心数据
Posted
技术标签:
【中文标题】从 UIViewController 中的 UITableView 中删除核心数据【英文标题】:Deleting Core Data from a UITableView within a UIViewController 【发布时间】:2012-04-29 12:49:42 【问题描述】:我在 UIViewController 中有一个 UITableView,这样我就可以在表格下方有一个 UILabel。这样做时,我在添加编辑/完成按钮时遇到了困难。我做不到传统的方式,所以我不得不使用以下想法做一个工作:
1)在viewdidload左上角创建编辑按钮:
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(editbutton)];
2) 创建代码,以便在单击编辑按钮时,表格视图变为可编辑,并将标题更改为完成。然后点击完成后,它会回到说编辑。
-(IBAction)editbutton
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(donebutton)];
[tableView setEditing:YES animated:YES];
-(IBAction)donebutton
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(editbutton)];
[tableView setEditing:NO animated:YES];
这部分一切正常。我只是为了完整性把它放进去。单击编辑按钮时,表格视图变为可编辑的,我可以单击完成并恢复正常。我的问题是单击删除按钮(单击一行旁边的红色减号按钮后)不会删除该行。我试过以下代码:
注意: 1)上下文已在 .h 文件中声明为: @property (nonatomic, 保留) NSManagedObjectContext *context; 并在.m文件中合成。 2)我在.h文件中声明了@property(非原子,保留)NSFetchedResultsController *fetchedResultsController,然后在.m文件中声明了@synthesize fetchedResultsController = _fetchedResultsController
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
if (editingStyle == UITableViewCellEditingStyleDelete)
// Delete the managed object for the given index path
[context deleteObject:[_fetchedResultsController objectAtIndexPath:indexPath]];
// Save the context.
NSError *error = nil;
if (![context save:&error])
/*
Replace this implementation with code to handle the error appropriately.
abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
*/
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
编辑:
好的,我找到了一些解决方案。我使用以下代码删除了我的核心数据:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
if (editingStyle == UITableViewCellEditingStyleDelete)
// Delete the managed object for the given index path
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
[context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];
// Save the context.
NSError *error = nil;
if (![context save:&error])
/*
Replace this implementation with code to handle the error appropriately.
abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
*/
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
[self fetchedresults];
[self.tableView reloadData];
我的新问题是当我点击删除时。该行被删除,但仍保留在那里,空白行上的红色减号按钮。我仍然可以单击该行(通常会编辑数据),但没有要加载的数据。
编辑 2:
我忘了添加,为了让它工作,我添加了这个:
- (NSFetchedResultsController *)fetchedResultsController
if (_fetchedResultsController != nil)
return _fetchedResultsController;
// Set up the fetched results controller.
// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Record" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"activity" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:@"Master"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error])
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
return _fetchedResultsController;
编辑 3:
这是获取结果的作用:
- (void)fetchedresults
NSManagedObjectContext *moc = [self context];
NSEntityDescription *entityDescription = [NSEntityDescription
entityForName:@"Record" inManagedObjectContext:moc];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
initWithKey:@"activity" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
NSError *error = nil;
NSArray *array = [moc executeFetchRequest:request error:&error];
if (array == nil)
// Deal with error...
float tot = [[array valueForKeyPath:@"@sum.cpdhours"] floatValue];
totalhours.text = [NSString stringWithFormat:@"%.1f", tot];
【问题讨论】:
【参考方案1】:我认为你拥有的 managedObjectContext 属性实际上是你的 fetchedResultsController 上下文的父上下文,因此当你使用它删除一个实体时,fetchedResultsController 不会知道它应该重新获取和更新 tableview。尝试调用 [self.fetchedResultsController.managedObjectContext deleteItem:yourItem]。
也许这与我在 iPhone 上写的不完全一样,但你明白了。您是否还确保实现获取的结果控制器委托方法来更新您的 tableview?
【讨论】:
尝试使用代码 [self.fetchedResultsController.managedObjectContext deletedObjects:[_fetchedResultsController objectAtIndexPath:indexPath]]。因为 deleteitem 无效,但代码有一个错误:接收器类型 NSManagedObjectContext 例如消息未声明具有选择器“已删除对象”的方法。此外,错误出现在表更新之前。我在上面显示的错误语句中收到错误 (NSLog(@"Unresolved error %@, %@", error, [error userInfo]) [self.fetchedResultsController.managedObjectContext deleteObject:self.objectToDelete] 这是来自我的代码,它运行良好。【参考方案2】:您可能需要重新缓存您的 NSResultFetchedController。在您的 NSFetchedResultController 初始化函数中,您将获取结果缓存到名为“Master”的缓存中。这可能解释了您遇到的行为。
在设置 NSFetchedResultController 时,您可以通过将缓存名称设置为 nil 来不使用任何缓存
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];
或者您在删除 NSManagedObject 后立即删除缓存。
[NSFetchedResultController deleteCacheWithName:@"Master"];
【讨论】:
【参考方案3】:您使用的是NSFetchedResultsController
吗?如果没有,请尝试一下,您完全不用担心重新加载表格。
此外,绝对不需要使用自定义按钮。只需坚持使用 .editButtonItem
并覆盖 -setEditing:animated:
。
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
[super setEditing:editing animated:animated];
[self.tableView setEditing:editing animated:animated];
【讨论】:
你的第二部分成功了!!!谢谢!!但关于你答案的第一部分,请参阅编辑 2,我正在使用 NSFetchedResultsController 并且它仍然没有刷新。[self fetchedresults];
是做什么的?
查看我的新编辑。我认为这是一个获取的视图控制器,可以在从其他屏幕返回时很好地更新数据。【参考方案4】:
Swift:就我而言,我想在用户退出后彻底清除我的tableView
:
func clearData()
NSFetchedResultsController.deleteCacheWithName("MyCache")
let indices = tableView.allIndices
let moc = NSManagedObjectContext.MR_defaultContext()
let fetchRequest = NSFetchRequest(entityName: "MyEntity")
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
saveMoc()
do
try moc.persistentStoreCoordinator!.executeRequest(deleteRequest, withContext: moc)
try fetchedResultsController.performFetch()
tableView.beginUpdates()
tableView.deleteRowsAtIndexPaths(indices, withRowAnimation: .Automatic)
tableView.endUpdates()
catch let e as NSError
print(e)
我做了一个扩展来为我的 tableview 获取所有 NSIndexPath
s:
extension UITableView
var allIndices: [NSIndexPath]
var indices = [NSIndexPath]()
let sections = self.numberOfSections
if sections > 0
for s in 0...sections - 1
let rows = self.numberOfRowsInSection(s)
if rows > 0
for r in 0...rows - 1
let index = NSIndexPath(forRow: r, inSection: s)
indices.append(index)
return indices
【讨论】:
以上是关于从 UIViewController 中的 UITableView 中删除核心数据的主要内容,如果未能解决你的问题,请参考以下文章
Swift - 从 NavigationController 中的 UIViewController 转到 TabBarController 中的 UIViewController