当我使用添加函数时断言失败

Posted

技术标签:

【中文标题】当我使用添加函数时断言失败【英文标题】:Assertion failure when i use the Add Function 【发布时间】:2011-07-19 09:02:33 【问题描述】:

在一个表中,我有 3 个索引,每个索引调用一个函数。在每个函数中,都有一个添加按钮,用于将数据添加到 CoreData。前 2 个有效,但是当我按第三个索引并按 Add 时,出现此错误。

2011-07-19 16:57:11.079 CoreDataMelaka[2704:207] * **Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1447.6.4/UITableView.m:976**
2011-07-19 16:57:11.080 CoreDataMelaka[2704:207] **Serious application error.  Exception was caught during Core Data change processing.  This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification.  Invalid update: invalid number of rows in section 0.  The number of rows contained in an existing section after the update (0) must be equal to the number of rows contained in that section before the update (0), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted). with userInfo (null)****

这是我调用的第三类代码

@implementation MainFoodsInfoController

@synthesize mainfoods;
@synthesize mainfoodsarray;
@synthesize fetchedResultsController;
@synthesize tableView;
@synthesize foodsbutton;
@synthesize editfoodsbutton;
@synthesize addfoodsbutton;


-(IBAction) foodslist:(id) sender 

    [self dismissModalViewControllerAnimated:YES];



-(IBAction) addmainfoods:(id)sender 

    NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
    AddMainFoodsController *addmainfoodsController=[[AddMainFoodsController alloc] initWithNibName:@"AddMainFoodsController" bundle:nil];
    addmainfoodsController.delegate=self;   
    addmainfoodsController.mainfoods =  [NSEntityDescription insertNewObjectForEntityForName:@"MainFoods" inManagedObjectContext:context];
    UINavigationController *navigatController=[[UINavigationController alloc] initWithRootViewController:addmainfoodsController];
    [self   presentModalViewController:navigatController animated:YES]; 
    [addmainfoodsController release];
    [navigatController release];



-(IBAction) editmainfoods:(id)sender 

    if([editfoodsbutton.title isEqualToString:@"Edit"]) 
    
        editfoodsbutton.title=@"Done"; 
        [self.tableView setEditing:YES animated:YES];
     
    else 
    
        editfoodsbutton.title=@"Edit"; 
        [self.tableView setEditing:NO animated:YES];
    


-(void) addmainfoodsController:(AddMainFoodsController *)controller selectedsave:(BOOL) save 

    NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
    if(!save) 
        [context deleteObject:controller.mainfoods];
     
    NSError *error; if(![context save:&error])
    
        NSLog(@"Unresolved error %@ %@", error, [error userInfo]); exit(-1);
     
    [self dismissModalViewControllerAnimated:YES];


- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 

    NSInteger count = [[self.fetchedResultsController sections] count];
    if (count == 0) 
    
        count = 1;
    
    return count;   


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 

    NSInteger numofRows = 0;
    if ([[self.fetchedResultsController sections] count] > 0) 
    
        id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
        numofRows = [sectionInfo numberOfObjects];
    
    return numofRows;


// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) 
     
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 
        cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator;
        

    // Configure the cell.
    NSManagedObject *managedObject = [fetchedResultsController objectAtIndexPath:indexPath];
    cell.textLabel.text = [[managedObject valueForKey:@"foodsname"] description];
    UIImage *pimage=[managedObject valueForKey:@"foodstableimage"]; 
    CGSize size=pimage.size; 
    CGFloat ratio = 0; if (size.width > size.height) 
    
        ratio = 44.0 / size.width;
     
    else 
    
        ratio = 44.0 / size.height;
    
    CGRect rect = CGRectMake(0.0, 0.0, ratio * size.width, ratio * size. height);
    UIGraphicsBeginImageContext(rect.size); 
    [pimage drawInRect:rect]; 
    cell.imageView.image=UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    return cell;


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 

    EditMainFoodsController *editmainfoodsController = [[EditMainFoodsController alloc] initWithNibName:@"EditMainFoodsController" bundle:nil];
    MainFoods *selectedmainfoods = (MainFoods *) [fetchedResultsController objectAtIndexPath:indexPath];
    editmainfoodsController.mainfoods= selectedmainfoods;
    UINavigationController *naviggController=[[UINavigationController alloc] initWithRootViewController:editmainfoodsController];
    [self presentModalViewController:naviggController animated:YES];


// Override to support editing the table view.
- (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]];
        NSError *error; if (![context save:&error]) 
        
            // Handle the error...
        
       


- (void)viewWillAppear:(BOOL)animated 
    [super viewWillAppear:animated];
    NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:[NSEntityDescription entityForName:@"MainFoods" inManagedObjectContext:context]];
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"foodsname" ascending:YES];
    NSArray *sortDescriptors =[[NSArray alloc] initWithObjects:sortDescriptor,nil]; 
    [fetchRequest setSortDescriptors:sortDescriptors];
    self.tableView.rowHeight=44.0;
    NSError *error=nil;
    mainfoodsarray=(NSMutableArray *)[context executeFetchRequest:fetchRequest error:&error];   
    [sortDescriptor release];
    [sortDescriptors release];
    [fetchRequest release];
    [self.tableView reloadData];     


- (void)viewDidLoad 
    [super viewDidLoad];
    self.title=@"Foods Info";
    NSError *error;
    if (![[self fetchedResultsController] performFetch:&error]) 
        // Handle the error...
       




- (NSFetchedResultsController *)fetchedResultsController 
    if (fetchedResultsController != nil) 
        return fetchedResultsController;
    

    CoreDataMelakaAppDelegate *appDelegate = (CoreDataMelakaAppDelegate *)[[UIApplication sharedApplication] delegate];
    NSManagedObjectContext *context = [appDelegate managedObjectContext];
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:[NSEntityDescription entityForName:@"MainFoods" inManagedObjectContext:context]];
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"foodsname" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    [fetchRequest setSortDescriptors:sortDescriptors];
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:@"Root"];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;
    [aFetchedResultsController release];
    return fetchedResultsController;
    

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath 
    switch(type) 
        case NSFetchedResultsChangeInsert:
            [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
        case NSFetchedResultsChangeDelete:
            [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
    


- (void)didReceiveMemoryWarning 
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc. that aren't in use.


- (void)viewDidUnload 
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;



- (void)dealloc 
    [foodsbutton release];
    [editfoodsbutton release];
    [addfoodsbutton release];
    [tableView release];
    [super dealloc];


@end

这是导致崩溃的添加类。当我按添加时,我希望调用这个类,但这会导致崩溃,其他 2 个类没有问题,只有这个有问题

@implementation AddMainFoodsController

@synthesize savebutton; 
@synthesize cancelbutton; 
@synthesize delegate; 
@synthesize foodsnewname; 
@synthesize foodsnewinfo; 
@synthesize foodsnewemailid;
@synthesize foodsnewcontactno;
@synthesize foodsimage1;
@synthesize foodsimage2;
@synthesize foodsimage3;
@synthesize foodstableimage;
@synthesize mainfoods;
@synthesize tempImage;

NSInteger countaddfoods = 0;

-(IBAction) cancel:(id) sender 

    [delegate addmainfoodsController: self selectedsave:NO];


-(IBAction) save:(id)sender
 
    mainfoods.foodsname = foodsnewname.text; 
    mainfoods.foodsemailid = foodsnewemailid.text; 
    mainfoods.foodscontactno = foodsnewcontactno.text;
    mainfoods.foodsinfo = foodsnewinfo.text;
    [delegate addmainfoodsController: self selectedsave:YES ];


-(IBAction) selectimagebutton1:(id)sender

    UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init] ;
    imagePicker.delegate = self;
    [self presentModalViewController:imagePicker animated:YES];
    [imagePicker release];


-(IBAction) selectimagebutton2:(id)sender

    UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init] ;
    imagePicker.delegate = self;
    [self presentModalViewController:imagePicker animated:YES];
    [imagePicker release];


-(IBAction) selectimagebutton3:(id)sender

    UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init] ;
    imagePicker.delegate = self;
    [self presentModalViewController:imagePicker animated:YES];
    [imagePicker release];


-(IBAction) selecttableimagebutton:(id)sender

    UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init] ;
    imagePicker.delegate = self;
    [self presentModalViewController:imagePicker animated:YES];
    [imagePicker release];



- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)selectedImage editingInfo:(NSDictionary *)editingInfo

    tempImage = selectedImage;
    countaddfoods = countaddfoods + 1;

    [self setImage];
    [self dismissModalViewControllerAnimated:YES]; 


-(void) setImage

    if (countaddfoods == 1)
    
        foodsimage1.image = tempImage;
        mainfoods.foodsimage1 = tempImage;
    
    else if (countaddfoods == 2)
    
        foodsimage2.image = tempImage;
        mainfoods.foodsimage2 = tempImage;
    
    else if (countaddfoods == 3)
    
        foodsimage3.image = tempImage;
        mainfoods.foodsimage3 = tempImage;
    
    else 
    
        foodstableimage.image = tempImage;
        mainfoods.foodstableimage = tempImage;
    


- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker

    [self dismissModalViewControllerAnimated:YES];


- (void)viewDidLoad 

    [super viewDidLoad]; self.title=@"New Foods"; 
    self.navigationItem.rightBarButtonItem = savebutton; 
    self.navigationItem.leftBarButtonItem = cancelbutton;


- (void)dealloc 
 
    [savebutton release]; 
    [cancelbutton release]; 
    [foodsnewname release]; 
    [foodsnewemailid release]; 
    [foodsnewcontactno release]; 
    [foodsnewinfo release];
    [foodsimage1 release];
    [foodsimage2 release];
    [foodsimage3 release];
    [foodstableimage release];
    [mainfoods release]; 
    [tempImage release];
    [super dealloc];
 

@end

【问题讨论】:

由于controller:didChangeObject:... 是由有效的方法触发的,所以这不是问题。无论如何,它都是样板文件。您需要提供失败的第三个 add 方法的代码。 【参考方案1】:

错误信息告诉你问题:

无效更新:第 0 节中的行数无效。 更新 (0) 后包含在现有节中的行必须是 等于该节之前包含的行数 update (0),加上或减去插入或删除的行数 该部分(插入 1 个,删除 0 个)。与 userInfo (null)**

在您的表格部分 (0) 中,您从零行开始,即一个空白部分。然后您添加了 1 行,因此 section(0) 行数应为 1,但 numberOfRowsInSection: 返回零。

这个问题有三个可能的原因:

    您没有在controllerWillChangeContent: 中使用beginUpdate 冻结tableview,以便tableview 在更新完成之前尝试重绘自身。 您的 numberOfRowsInSection 返回该部分的错误行数。 您正在多次插入一个托管对象,或者您的插入/更新验证失败。

没有代码就无法告诉您实际的问题。

【讨论】:

我已经添加了需要观察的类。提前感谢您的帮助。 您还有问题吗?如果是这样,那么我怀疑您的问题是由于您没有为您的属性使用自点符号,例如你应该使用self.tempImageself.mainFoods。如果您不注意属性中的关键对象,则可能随时释放导致崩溃。 我解决了。是的。属性上的点符号,我没有使用那些。谢谢@TechZen。你很讨厌! 添加一些缺失的自点符号解决了我的问题。我一直在努力解决这个问题。感谢一百万 @TechZen 和 @Harvin!【参考方案2】:
return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects];

至少对我有用

【讨论】:

【参考方案3】:

我遇到了同样的错误。我正在使用 NSFetchedResultsControllerDelegate 的委托。我评论了代表的其余部分,除了下面的。

func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)   
 self.tableView.reloadData()
 if self.fetchedResultsController.fetchedObjects?.count == 0 
     else 
  

如果您想使用所有委托,那么您需要正确管理行和部分。当您没有正确管理行和节时会发生此错误。

【讨论】:

以上是关于当我使用添加函数时断言失败的主要内容,如果未能解决你的问题,请参考以下文章

错误:断言失败:!_debugDuringDeviceUpdate 不是真正的颤振

断言失败第二次添加/删除

断言失败:闯入调试器

Pytest编写测试函数

CoreDataBooks 问题断言失败。

Mongo Shell 显示添加的文档,但在 Scalatest 中断言失败