Базовая ошибка данных «Запрос на получение должен иметь объект» - PullRequest
1 голос
/ 29 марта 2010

Я попытался добавить парсер TopSongs и файлы Core Data в свое приложение, и теперь оно успешно создается без ошибок или предупреждений. Однако, как только приложение загружается, оно падает, давая следующую причину:

ОБНОВЛЕНИЕ: у меня все работает, но мой TableView не показывает никаких данных, и приложение не реагирует на следующие точки останова.

Спасибо.

ОБНОВЛЕНИЕ: вот новый код, который не реагирует на точки останова.

- (NSInteger)numberOfSectionsInTableView:(UITableView *)table {
    return [[fetchedResultsController sections] count];
}

- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section {
    id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
    return [sectionInfo numberOfObjects];
}

- (void)viewDidUnload {
    [super viewDidUnload];
    self.tableView = nil;
    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:self.managedObjectContext];
    [self.tableView reloadData]; 
}

- (UITableViewCell *)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *kCellIdentifier = @"SongCell";
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellIdentifier] autorelease];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
        cell.textLabel.font = [UIFont boldSystemFontOfSize:14];
    }
    Incident *incident = [fetchedResultsController objectAtIndexPath:indexPath];
    cell.textLabel.text = [NSString stringWithFormat:NSLocalizedString(@"#%d %@", @"#%d %@"), incident.title];
    return cell;
}

- (void)tableView:(UITableView *)table didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [table deselectRowAtIndexPath:indexPath animated:YES];
    self.detailController.incident = [fetchedResultsController objectAtIndexPath:indexPath];
    [self.navigationController pushViewController:self.detailController animated:YES];
}

ОБНОВЛЕНИЕ: Вот код, в котором найдены все экземпляры выборки.

- (Category *)categoryWithName:(NSString *)name {
    NSTimeInterval before = [NSDate timeIntervalSinceReferenceDate];
#ifdef USE_CACHING
    // check cache
    CacheNode *cacheNode = [cache objectForKey:name];
    if (cacheNode != nil) {
        // cache hit, update access counter
        cacheNode.accessCounter = accessCounter++;
        Category *category = (Category *)[managedObjectContext objectWithID:cacheNode.objectID];
        totalCacheHitCost += ([NSDate timeIntervalSinceReferenceDate] - before);
        cacheHitCount++;
        return category;
    }
#endif
    // cache missed, fetch from store - if not found in store there is no category object for the name and we must create one
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:self.categoryEntityDescription];
    NSPredicate *predicate = [self.categoryNamePredicateTemplate predicateWithSubstitutionVariables:[NSDictionary dictionaryWithObject:name forKey:kCategoryNameSubstitutionVariable]];
    [fetchRequest setPredicate:predicate];
    NSError *error = nil;
    NSArray *fetchResults = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
    [fetchRequest release];
    NSAssert1(fetchResults != nil, @"Unhandled error executing fetch request in import thread: %@", [error localizedDescription]);

    Category *category = nil;
    if ([fetchResults count] > 0) {
        // get category from fetch
        category = [fetchResults objectAtIndex:0];
    } else if ([fetchResults count] == 0) {
        // category not in store, must create a new category object 
        category = [[Category alloc] initWithEntity:self.categoryEntityDescription insertIntoManagedObjectContext:managedObjectContext];
        category.name = name;
        [category autorelease];
    }
#ifdef USE_CACHING
    // add to cache
    // first check to see if cache is full
    if ([cache count] >= cacheSize) {
        // evict least recently used (LRU) item from cache
        NSUInteger oldestAccessCount = UINT_MAX;
        NSString *key = nil, *keyOfOldestCacheNode = nil;
        for (key in cache) {
            CacheNode *tmpNode = [cache objectForKey:key];
            if (tmpNode.accessCounter < oldestAccessCount) {
                oldestAccessCount = tmpNode.accessCounter;
                [keyOfOldestCacheNode release];
                keyOfOldestCacheNode = [key retain];
            }
        }
        // retain the cache node for reuse
        cacheNode = [[cache objectForKey:keyOfOldestCacheNode] retain];
        // remove from the cache
        [cache removeObjectForKey:keyOfOldestCacheNode];
    } else {
        // create a new cache node
        cacheNode = [[CacheNode alloc] init];
    }
    cacheNode.objectID = [category objectID];
    cacheNode.accessCounter = accessCounter++;
    [cache setObject:cacheNode forKey:name];
    [cacheNode release];
#endif
    totalCacheMissCost += ([NSDate timeIntervalSinceReferenceDate] - before);
    cacheMissCount++;
    return category;
}

А этот ...

- (void)fetch {
    NSError *error = nil;
    BOOL success = [self.fetchedResultsController performFetch:&error];
    NSAssert2(success, @"Unhandled error performing fetch at SongsViewController.m, line %d: %@", __LINE__, [error localizedDescription]);
    [self.tableView reloadData];
}

- (NSFetchedResultsController *)fetchedResultsController {
    if (fetchedResultsController == nil) {
        NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
        [fetchRequest setEntity:[NSEntityDescription entityForName:@"Song" inManagedObjectContext:managedObjectContext]];
        NSArray *sortDescriptors = nil;
        NSString *sectionNameKeyPath = nil;
        if ([fetchSectioningControl selectedSegmentIndex] == 1) {
            sortDescriptors = [NSArray arrayWithObjects:[[[NSSortDescriptor alloc] initWithKey:@"category.name" ascending:YES] autorelease], [[[NSSortDescriptor alloc] initWithKey:@"rank" ascending:YES] autorelease], nil];
            sectionNameKeyPath = @"category.name";
        } else {
            sortDescriptors = [NSArray arrayWithObject:[[[NSSortDescriptor alloc] initWithKey:@"rank" ascending:YES] autorelease]];
        }
        [fetchRequest setSortDescriptors:sortDescriptors];
        fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:sectionNameKeyPath cacheName:@"SongsCache"];
    }    
    return fetchedResultsController;
} 

Ответы [ 4 ]

0 голосов
/ 29 марта 2010

Я видел, как это происходило, когда NSEntityDescription, передаваемый запросу на выборку, равен нулю. Наиболее вероятной причиной этого является то, что у вас есть объект модели, имя которого отличается от имени, которое вы указали для entityForName. За исключением этого, это может быть ошибка в конфигурации вашего стека базовых данных или отсутствующая модель данных, но в качестве первого шага я бы порекомендовал сохранить результат entityForName в локальной переменной и разбить его, чтобы убедиться, что это не т ноль.

0 голосов
/ 29 марта 2010
  1. Ваше дополнительное кэширование, вероятно, является пустой тратой циклов, поскольку Core Data выполняет собственное кэширование внутри. Я готов поспорить, что вы скорее замедляете, чем ускоряете, не говоря уже о дополнительной памяти, которую вы потребляете.

  2. Где вы устанавливаете categoryEntityDescription? Это теперь показано в коде, который вы разместили. Вероятно, это ноль.

  3. Почему вы сохраняете NSEntityDescription?!? Они уже находятся в памяти из-за Базовых данных, и их сохранение - пустая трата времени, которое может привести к проблемам, если Базовые данные захотят выпустить их в какой-то момент.

обновление

Ваше кеширование определенно происходит не из кода Apple, потому что они знают, что кеш находится в Core Data.

Что касается NSEntityDescription, опять же, не сохраняют NSEntityDescription.

Вы на 100% уверены, что NSEntityDescription не ноль? Вы подтвердили это в отладчике? Вы проверяли это с недавно восстановленным NSEntityDescription?

обновление

Вам необходимо научиться использовать отладчик, поскольку это решит большинство ваших проблем с кодированием. Поместите точку останова в этот метод и запустите ваш код в отладчике. Затем, когда выполнение останавливается на этой точке останова, вы можете проверить значения переменных и узнать, что они в данный момент установлены. Это подтвердит или опровергнет ваши подозрения о том, что есть, а что нет.

Эта ошибка возникает, когда вы не можете установить Entity в NSFetchRequest, что на основании вашего кода означает, что сохраняемое свойство не устанавливается до вызова кода, который вы показали.

0 голосов
/ 29 марта 2010

Поскольку вы добавили файл модели вручную, находится ли файл .xcdatamodel внутри шага Компилировать источники в вашей цели?

Перейдите к записи «Цели» на панели «Группы и файлы» в XCode и щелкните треугольник раскрытия. Затем нажмите на треугольник раскрытия для вашего приложения. Затем проверьте, находится ли он в источниках компиляции. Если нет, щелкните правой кнопкой мыши по источнику компиляции, выберите «Добавить -> Существующий файл ...» и добавьте его.

Редактировать на основе обновлений:

ОБНОВЛЕНИЕ: вот новый код, который не отвечает на контрольные точки.

- (UITableViewCell *)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)table didSelectRowAtIndexPath:(NSIndexPath *)indexPath

Ваш контроллер вида установлен как UITableViewDataSource / UITableViewDelegate для вашего UITableView? Если нет, эти методы не будут вызваны.

0 голосов
/ 29 марта 2010

Основываясь на опубликованном коде и описании проблемы, я подозреваю, что свойство categoryEntityDescription возвращает ноль.

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