Сбой при попытке получить NSManagedObject из NSFetchedResultsController после 25 объектов? - PullRequest
0 голосов
/ 23 декабря 2010

Я относительно новичок в Core Data на iOS, но, думаю, мне стало лучше.Однако я столкнулся со странным сбоем в одном из моих приложений и не смог этого понять.

У меня примерно 40 объектов в Базовых данных, представленных в UITableView.При нажатии на ячейку появляется UIActionSheet, предоставляя пользователю UIActionSheet с параметрами, связанными с выбранной ячейкой.Чтобы я мог ссылаться на выбранный объект, я объявляю NSIndexPath в своем заголовке с именем «lastSelection» и делаю следующее при представлении UIActionSheet:

// Each cell has a tag based on its row number (i.e. first row has tag 0)
lastSelection = [NSIndexPath indexPathForRow:[sender tag] inSection:0];
 NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:lastSelection];
 BOOL onDuty = [[managedObject valueForKey:@"onDuty"] boolValue];
 UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"Status" delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
 if(onDuty) {
  [actionSheet addButtonWithTitle:@"Off Duty"];
 } else {
  [actionSheet addButtonWithTitle:@"On Duty"];
 }
    actionSheet.actionSheetStyle = UIActionSheetStyleBlackOpaque;

 // Override the typical UIActionSheet behavior by presenting it overlapping the sender's frame.  This makes it more clear which cell is selected.
 CGRect senderFrame = [sender frame];
 CGPoint point = CGPointMake(senderFrame.origin.x + (senderFrame.size.width / 2), senderFrame.origin.y + (senderFrame.size.height / 2));
 CGRect popoverRect = CGRectMake(point.x, point.y, 1, 1);
    [actionSheet showFromRect:popoverRect inView:[sender superview] animated:NO];
    [actionSheet release];

Когда UIActionSheet закрывается с помощью кнопки, следующееКод называется:

- (void)actionSheet:(UIActionSheet *)actionSheet willDismissWithButtonIndex:(NSInteger)buttonIndex {
 // Set status based on UIActionSheet button pressed
 if(buttonIndex == -1) {
  return;
 }

 NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:lastSelection];

 if([actionSheet.title isEqualToString:@"Status"]) {
  if([[actionSheet buttonTitleAtIndex:buttonIndex] isEqualToString:@"On Duty"]) {
   [managedObject setValue:[NSNumber numberWithBool:YES] forKey:@"onDuty"];
   [managedObject setValue:@"onDuty" forKey:@"status"];
  } else {
   [managedObject setValue:[NSNumber numberWithBool:NO] forKey:@"onDuty"];
   [managedObject setValue:@"offDuty" forKey:@"status"];
  }
 }

 NSError *error;
 [self.managedObjectContext save:&error];

 [tableView reloadData];
}

Возможно, это не самый эффективный код (извините, я новичок!), но он работает.То есть для первых 25 пунктов в списке.При выборе 26-го элемента или выше появится UIActionSheet, но если он будет отклонен кнопкой, я получу множество ошибок, включая любую из следующих:

[__NSCFArray section]: unrecognized selector sent to instance 0x4c6bf90

Program received signal:  “EXC_BAD_ACCESS”

[_NSObjectID_48_0 section]: unrecognized selector sent to instance 0x4c54710

[__NSArrayM section]: unrecognized selector sent to instance 0x4c619a0

[NSComparisonPredicate section]: unrecognized selector sent to instance 0x6088790

[NSKeyPathExpression section]: unrecognized selector sent to instance 0x4c18950

Если я закомментирую NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:lastSelection]; он больше не падает, поэтому я считаю, что это как-то связано с этим.Может ли кто-нибудь предложить какое-либо понимание?Пожалуйста, дайте мне знать, если мне нужно включить любую другую информацию.Спасибо!

РЕДАКТИРОВАТЬ: Интересно, что мой код fetchedResultsController каждый раз возвращает новый объект.Это ожидалось, или это могло быть причиной моей проблемы?Код выглядит так:

- (NSFetchedResultsController *)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:@"Employee" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:80];

    // Edit the sort key as appropriate.
 NSString *sortKey;
 BOOL ascending;
 if(sortControl.selectedSegmentIndex == 0) {
  sortKey = @"startTime";
  ascending = YES;
 } else if(sortControl.selectedSegmentIndex == 1) {
  sortKey = @"name";
  ascending = YES;
 } else {
  sortKey = @"onDuty";
  ascending = NO;
 }
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:ascending];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];

    [fetchRequest setSortDescriptors:sortDescriptors];

    // Edit the section name key path and cache name if appropriate.
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Root"];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    [aFetchedResultsController release];
    [fetchRequest release];
    [sortDescriptor release];
 [sortDescriptors release];

    NSError *error = nil;
    if (![fetchedResultsController_ performFetch:&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. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
         */
        //NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return fetchedResultsController_;
}

Это происходит, когда я устанавливаю точку останова:

(gdb) po [self fetchedResultsController]
<NSFetchedResultsController: 0x61567c0>
(gdb) po [self fetchedResultsController]
<NSFetchedResultsController: 0x4c83630>

Ответы [ 2 ]

0 голосов
/ 23 декабря 2010

Разобрался!Похоже, это была проблема с автоматически выпущенными объектами.

Когда я включил NSZombieEnabled, я получил это:

*** -[NSIndexPath section]: message sent to deallocated instance 0xa674530

Я просто изменил lastSelection = [NSIndexPath indexPathForRow:[sender tag] inSection:0]; на lastSelection = [[NSIndexPath indexPathForRow:[sender tag] inSection:0] retain];, и это позаботилосьэто.

0 голосов
/ 23 декабря 2010

Возможно, что self.fetchedResultsController указывает на неправильную ячейку памяти. Вам нужно будет проверить, сохранился ли объект.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...