我是iOS开发/ CoreData的新手,并且已经搜索了我的具体问题的答案,但还没有找到答案。
我有一个TableView,包含我数据库中的一些对象。每个对象都有一个属性“name”。如果我打开其中一个对象的详细信息视图并使用“返回”按钮返回tableView,一切正常。如果我没有更改“名称”TextField并按“完成”按钮返回到我的tableView,它也可以工作。一旦我在“名称”TextField中做了一些更改,我就会收到此错误:
无效更新:第0节中的行数无效。更新后的现有部分中包含的行数(9)必须等于更新前该部分中包含的行数(9),或者减去从该部分插入或删除的行数(插入0,删除1),加上或减去移入或移出该部分的行数(0移入,0移出)。
为什么要删除某个对象?
这是我的DetailsStaticTableViewController.m的代码:
#import "WeinStaticTableViewController.h"
#import "Wein.h"
#import "JSMToolBox.h"
@interface WeinStaticTableViewController ()
@end
@implementation WeinStaticTableViewController
@synthesize nameTextView;
@synthesize landTextView;
@synthesize herstellerTextView;
@synthesize wein = _wein;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
if (self.wein != nil) {
self.nameTextView.text = self.wein.name;
}
}
- (void) viewDidDisappear:(BOOL)animated
{
[[JSMCoreDataHelper managedObjectContext] rollback];
[super viewDidDisappear:animated];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
[self setNameTextView:nil];
[self setLandTextView:nil];
[self setHerstellerTextView:nil];
self.wein = nil;
}
- (IBAction)barButtonItemDonePressed:(id)sender
{
NSLog(@"%s", __PRETTY_FUNCTION__);
if (self.wein != nil) {
self.wein.name = self.nameTextView.text;
[JSMCoreDataHelper saveManagedObjectContext:[JSMCoreDataHelper managedObjectContext]];
}
[self.navigationController popViewControllerAnimated:YES];
}
@end
以下是我的JSMCoreDataHelper.m的代码:
#import "JSMCoreDataHelper.h"
@implementation JSMCoreDataHelper
+ (NSString*) directoryForDatabaseFilename
{
return [NSHomeDirectory() stringByAppendingString:@"/Library/Private Documents"];
}
+ (NSString*) databaseFileName
{
return @"database.sqlite";
}
+ (NSManagedObjectContext*) managedObjectContext
{
static NSManagedObjectContext *managedObjectContext;
if (managedObjectContext != nil) {
return managedObjectContext;
}
NSError *error;
// Verzeichnis unter dem das Datenbank-File abgespeichert werden soll, wird neu erzeugt, falls es noch nicht existiert.
[[NSFileManager defaultManager] createDirectoryAtPath:[JSMCoreDataHelper directoryForDatabaseFilename] withIntermediateDirectories:YES attributes:nil error:&error];
if (error) {
NSLog(@"Fehler: %@", error.localizedDescription);
return nil;
}
NSString *path = [NSString stringWithFormat:@"%@/%@", [JSMCoreDataHelper directoryForDatabaseFilename], [JSMCoreDataHelper databaseFileName]];
NSURL *url = [NSURL fileURLWithPath:path];
NSManagedObjectModel *managedModel = [NSManagedObjectModel mergedModelFromBundles:nil];
NSPersistentStoreCoordinator *storeCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:managedModel];
if (! [storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:nil error:&error]) {
NSLog(@"Fehler: %@", error.localizedDescription);
return nil;
}
managedObjectContext = [[NSManagedObjectContext alloc] init];
managedObjectContext.persistentStoreCoordinator = storeCoordinator;
return managedObjectContext;
}
+ (id) insertManagedObjectOfClass: (Class) aClass inManagedObjectContext: (NSManagedObjectContext*) managedObjectContext
{
NSManagedObject *managedObject = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass(aClass) inManagedObjectContext:managedObjectContext];
return managedObject;
}
+ (BOOL) saveManagedObjectContext: (NSManagedObjectContext*) managedObjectContext
{
NSError *error;
if (! [managedObjectContext save:&error]) {
NSLog(@"Fehler: %@", error.localizedDescription);
return NO;
}
return YES;
}
+ (NSArray*) fetchEntitiesForClass: (Class) aClass withPredicate: (NSPredicate*) predicate inManagedObjectContext: (NSManagedObjectContext*) managedObjectContext
{
NSError *error;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:NSStringFromClass(aClass) inManagedObjectContext:managedObjectContext];
fetchRequest.entity = entityDescription;
fetchRequest.predicate = predicate;
NSArray *items = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (error) {
NSLog(@"Fehler: %@", error.localizedDescription);
return nil;
}
return items;
}
+ (BOOL) performFetchOnFetchedResultsController: (NSFetchedResultsController*) fetchedResultsController
{
NSError *error;
if (! [fetchedResultsController performFetch:&error]) {
NSLog(@"Fehler: %@", error.localizedDescription);
return NO;
}
return YES;
}
@end
最后是我的MainTableViewController的numberOfSections和numberOfRowsInSection:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects];
}
任何线索都可以帮助......谢谢!
答案 0 :(得分:1)
使用NSFetchedResultsController继承我的代码,这适用于管理CoreData的代码。
希望这有帮助。
#import "Person.h"
#import "mainViewController.h"
#import "JSMCoreDataHelper.h"
#import "staticInfoViewController.h"
@implementation mainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Load From CoreData
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
// Update to handle the error appropriately.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
exit(-1); // Fail
}
}
#pragma mark - TableView DataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
Person *p = [_fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = [NSString stringWithFormat:@"Name: %@", p.name];
}
#pragma mark - TableView Delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
staticInfoViewController *info = [[staticInfoViewController alloc] initWithNibName:@"staticInfoViewController" bundle:[NSBundle mainBundle]];
info.currentPerson = [_fetchedResultsController objectAtIndexPath:indexPath];
[self.navigationController pushViewController:info animated:YES];
}
#pragma mark - Set NSFetchedResultsController
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:@"Person" inManagedObjectContext:[JSMCoreDataHelper managedObjectContext]];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc]
initWithKey:@"name" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:[JSMCoreDataHelper managedObjectContext] sectionNameKeyPath:nil
cacheName:@"cache"];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
#pragma mark - NSFetchedResultsController Delegate
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller is about to start sending change notifications, so prepare the table view for updates.
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray
arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray
arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id )sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller has sent all current change notifications, so tell the table view to process all updates.
[self.tableView endUpdates];
}
@end
答案 1 :(得分:0)
您在UI和核心数据中的数据数量错误。行计数dosnt匹配UI和核心数据。你已经daleted一行但UI / fetchresultcontroller不知道并尝试从数据库中读取它。更改后重新获取或实现获取结果控制器委托:
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath;
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type;
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller;
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller;
不要忘记将获取结果控制器设置为self。(viel spass)