我的 iOS fetchrequest 的奇怪行为有两个部分

Posted

技术标签:

【中文标题】我的 iOS fetchrequest 的奇怪行为有两个部分【英文标题】:Weird behavior on my iOS fetchrequest with two sections 【发布时间】:2015-11-25 16:07:05 【问题描述】:

在我的带有 2 个部分 的 tableviewcontroller 中,构建工作正常,但应用程序崩溃。当我打开详细视图控制器以将项目添加到数据存储时,一开始崩溃,因此一个部分将有一个项目,而另一个部分将具有零项目(因为生成这些部分的两个不同谓词)。

如果我只设置一个部分,构建应用程序,存储两个不同的项目,每个部分一个,一切都很好,每个部分的项目数量相同。当我再次设置两个部分时,重新构建应用程序,运行并创建一个新项目,这些部分的编号不同:代码将保存项目,返回 tableview 将使应用程序崩溃。这是为什么呢?

#import "hommedicineTableViewController.h"
#import "cella2.h"

@interface hommedicineTableViewController ()

@end

@implementation hommedicineTableViewController
@synthesize section2Items = _section2Items;
static NSString *CellIdentifier = @"cell3";

- (NSManagedObjectContext *)managedObjectContext 
    NSManagedObjectContext *context = nil;
    id delegate = [[UIApplication sharedApplication] delegate];
    if ([delegate performSelector:@selector(managedObjectContext)]) 
        context = [delegate managedObjectContext];
    
    return context;


- (void)viewDidLoad 
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor colorWithRed:(220/255.f) green:(237/255.f) blue:(231/255.f) alpha:1.0];
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    [self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([cella2 class]) bundle:nil] forCellReuseIdentifier:NSStringFromClass([cella2 class])];
    [self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([cella2 class]) bundle:nil] forCellReuseIdentifier:CellIdentifier];


- (void)viewDidAppear:(BOOL)animated 
    [super viewDidAppear:animated];
    NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
    NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"archivio like%@", @"in*"];
    NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"archivio like%@", @"ar*"];
    NSFetchRequest *fetchRequest1 = [[NSFetchRequest alloc] initWithEntityName:@"Medicine"];
    NSFetchRequest *fetchRequest2 = [[NSFetchRequest alloc] initWithEntityName:@"Medicine"];
    NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"archivio" ascending:NO];
    NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"scadenza" ascending:YES];
    [fetchRequest1 setSortDescriptors:[NSArray arrayWithObjects: sortDescriptor1, sortDescriptor2, nil]];
    NSSortDescriptor *sortDescriptor3 = [[NSSortDescriptor alloc] initWithKey:@"archivio" ascending:YES];
    [fetchRequest2 setSortDescriptors:[NSArray arrayWithObjects: sortDescriptor3, sortDescriptor2, nil]];
    [fetchRequest1 setPredicate:predicate1];
    [fetchRequest2 setPredicate:predicate2];
    self.contactarray = [[managedObjectContext executeFetchRequest:fetchRequest1 error:nil] mutableCopy];
    _section2Items = [[managedObjectContext executeFetchRequest:fetchRequest2 error:nil] mutableCopy];
    [self.tableView reloadData];


- (void)didReceiveMemoryWarning 
    [super didReceiveMemoryWarning];


- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
    return 2;


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
    if (section == 0) 
            return [self.contactarray count];
     else if (section == 1) 
            return [_section2Items count];
     else 
    return 0;
    


- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath 
    cella2 *tcell = (cella2 *)cell;
    NSManagedObject *device1 = [self.contactarray objectAtIndex:indexPath.row];
    NSManagedObject *device2 = [_section2Items objectAtIndex:indexPath.row];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"dd-MM-YYYY"];
    NSString *dateString = [dateFormatter stringFromDate:[device1 valueForKey:@"scadenza"]];
    if (indexPath.section == 0) 
                                tcell.immagine1.image = [[UIImage alloc] initWithData:[device1 valueForKey:@"picture"]];
                                tcell.label1.text = [NSString stringWithFormat:@"%@", [device1 valueForKey:@"nominativo"]];
                                tcell.label2.text = [NSString stringWithFormat:@"Scadenza: %@", dateString];
                                tcell.label3.text = [NSString stringWithFormat:@"%@", [device1 valueForKey:@"archivio"]];
     else 
                                tcell.label2.textColor = [UIColor colorWithRed:0.0f/255.0f green:0.0f/255.0f blue:0.0f/255.0f alpha:1.0f];
                                tcell.immagine1.image = [[UIImage alloc] initWithData:[device2 valueForKey:@"picture"]];
                                tcell.label1.text = [NSString stringWithFormat:@"%@", [device2 valueForKey:@"nominativo"]];
                                tcell.label2.text = [NSString stringWithFormat:@"Scadenza: %@", dateString];
                                tcell.label3.text = [NSString stringWithFormat:@"%@", [device2 valueForKey:@"archivio"]];
    


- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath 
        cella2 *cell = (cella2 *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        [self configureCell:cell atIndexPath:indexPath];
        return cell;


- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath 
    return YES;


- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
    NSManagedObjectContext *context = [self managedObjectContext];
    if (editingStyle == UITableViewCellEditingStyleDelete) 
        [context deleteObject:[self.contactarray objectAtIndex:indexPath.row]];
        NSError *error = nil;
        if (![context save:&error]) 
            NSLog(@"Can't Delete! %@ %@", error, [error localizedDescription]);
            return;
        
        [self.contactarray removeObjectAtIndex:indexPath.row];
        [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
    


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
    [self performSegueWithIdentifier:@"seg2" sender:self];


- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
    if ([[segue identifier] isEqualToString:@"seg2"]) 
        NSManagedObject *selectedDevice = [self.contactarray objectAtIndex:[[self.tableView indexPathForSelectedRow] row]];
        DettaglioViewController *destViewController = segue.destinationViewController;
        destViewController.contactdb = selectedDevice;
    


 @end

【问题讨论】:

应用崩溃时收到的错误是什么? 核心数据修改后如何触发表重载? 有没有试过给项目加异常断点(Breakpoint tab/+/Add Exception Breakpoint)? 【参考方案1】:

我怀疑问题出在你的configureCell:atIndexPath: 方法上,特别是这两行:

NSManagedObject *device1 = [self.contactarray objectAtIndex:indexPath.row];
NSManagedObject *device2 = [_section2Items objectAtIndex:indexPath.row];

如果一个部分的项目多于另一部分,则其中一行将尝试越界访问数组索引(即 indexPath.row 将大于或等于数组计数)。只需将这些行移到 if/else 的相关子句中即可:

if (indexPath.section == 0) 
    NSManagedObject *device1 = [self.contactarray objectAtIndex:indexPath.row];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"dd-MM-YYYY"];
    NSString *dateString = [dateFormatter stringFromDate:[device1 valueForKey:@"scadenza"]];
    tcell.immagine1.image = [[UIImage alloc] initWithData:[device1 valueForKey:@"picture"]];
    tcell.label1.text = [NSString stringWithFormat:@"%@", [device1 valueForKey:@"nominativo"]];
    tcell.label2.text = [NSString stringWithFormat:@"Scadenza: %@", dateString];
    tcell.label3.text = [NSString stringWithFormat:@"%@", [device1 valueForKey:@"archivio"]];
 else 
    NSManagedObject *device2 = [_section2Items objectAtIndex:indexPath.row];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"dd-MM-YYYY"];
    NSString *dateString = [dateFormatter stringFromDate:[device2 valueForKey:@"scadenza"]];
    tcell.label2.textColor = [UIColor colorWithRed:0.0f/255.0f green:0.0f/255.0f blue:0.0f/255.0f alpha:1.0f];
    tcell.immagine1.image = [[UIImage alloc] initWithData:[device2 valueForKey:@"picture"]];
    tcell.label1.text = [NSString stringWithFormat:@"%@", [device2 valueForKey:@"nominativo"]];
    tcell.label2.text = [NSString stringWithFormat:@"Scadenza: %@", dateString];
    tcell.label3.text = [NSString stringWithFormat:@"%@", [device2 valueForKey:@"archivio"]];

有更简洁的编码方式,但我希望你能明白。

【讨论】:

感谢 pbasdf,它运行了!!

以上是关于我的 iOS fetchrequest 的奇怪行为有两个部分的主要内容,如果未能解决你的问题,请参考以下文章

iOS7 中选定 UITableViewCell 的奇怪行为

navigationBar 和 MPMoviePlayerController 的极其奇怪的行为。 iOS中的错误或我的错误?

iOS javascript POST请求奇怪的行为

使用选项卡控制器时出现奇怪的滚动行为 - iOS

NSFetchedResultsController 和关系

ios - 音量控制的非常奇怪的行为