В моем приложении iOS я пытаюсь сохранить значения через данные ядра в sqlite db в одном представлении, а затем получить в другом. Глядя на базу данных, сохранение выглядит нормально, объекты находятся в db, как и ожидалось. Если я перейду к представлению коллекции, результат будет корректным. Однако, если я достаточно приложение и снова открываю, после извлечения в виде коллекции отображается правильное количество ячеек (строк), но все они пустые ??? Счетчик выборки всегда возвращает 0, но, создав аргументы командной строки, чтобы увидеть sql, он предполагает, что он выбирает правильное количество строк. Моя выборка запрос выглядит следующим образом:Основные данные, кажется, извлекают пустые объекты
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:@"Player" inManagedObjectContext:self.context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc]
initWithKey:@"surname" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:context sectionNameKeyPath:nil
cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
NSLog(@"fetch count %@",[NSString stringWithFormat:@"%d",[theFetchedResultsController.fetchedObjects count]]);
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
и это производит следующий журнал для SQL с помощью инструмента командной строки ARGS:
CoreData: sql: SELECT 0, t0.Z_PK FROM ZPLAYER t0 ORDER BY t0.ZSURNAME DESC
2015-02-09 23:56:39.522 teamPicker[290:20878] CoreData: annotation: sql connection fetch time: 0.0013s
2015-02-09 23:56:39.523 teamPicker[290:20878] CoreData: annotation: total fetch execution time: 0.0020s for 4 rows.
2015-02-09 23:56:39.562 teamPicker[290:20878] CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZEMAIL, t0.ZFORENAME, t0.ZMOBNUM, t0.ZMUGSHOT, t0.ZSURNAME, t0.ZTWITTER, t0.ZPROFILE FROM ZPLAYER t0 WHERE t0.Z_PK IN (?,?,?,?) ORDER BY t0.ZSURNAME DESC LIMIT 20
2015-02-09 23:56:39.711 teamPicker[290:20878] CoreData: annotation: sql connection fetch time: 0.1408s
2015-02-09 23:56:39.711 teamPicker[290:20878] CoreData: annotation: total fetch execution time: 0.1495s for 4 rows.
Как вы можете видеть, как представляется, запустите два запроса, которые я нахожу странными, но как im noob, я бы не знал, если это не так, как это работает. То, что это, кажется, предполагает, однако, что, несмотря на выборки количества отчетов 0, он принес 4 строки, которые в этот момент все то будет в там
Вот мои представления коллекции метода DataSource в случае, который помогает:
#pragma mark - UICollectionView Datasource
// 1
- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section {
id sectionInfo =
[[_fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
// 2
- (NSInteger)numberOfSectionsInCollectionView: (UICollectionView *)collectionView {
return 1;
}
// 3
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
Player *info = [_fetchedResultsController objectAtIndexPath:indexPath];
playerPhotoCell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"playerCell" forIndexPath:indexPath];
cell.playerImage.image = [UIImage imageWithData:info.mugshot];
cell.playerLabel.text = info.forename;
cell.backgroundColor = [UIColor whiteColor];
return cell;
}
Ive, возможно, сделал некоторые вопиющие и основные ошибки, но я проклят, если я смогу их обнаружить или найти ответы. Я был бы очень благодарен, если кто-нибудь может помочь мне указать в правильном направлении. Спасибо за чтение
EDIT: благодаря pbasdf за указание на ошибку в моем вызове рассчитывать выборки, я переехал этот код в нужное место, и это действительно возвращает правильный количество объектов
Как недавно обещал , мой playerPhotoCell - это просто скрипт с двумя свойствами в файле h, чтобы действовать как выходы для представления изображения и ярлык, который я добавил в ячейку в раскадровке. В файле .m нет методов, так как я думал, что мой код viewController может просто ссылаться на выходные точки и устанавливать их значения - действительно, это работает, если вы просматриваете в том же сеансе, который был сохранен, поскольку ячейка заполнена правильно - проблема возникает, когда приложение было закрыто и перезагружено - правильное количество ячеек загружено, но все просто имеют белый фон и не имеют информации
Далее EDIT: Как я уже сказал, я добавил простую проверку cellForItemAtIndexPath, чтобы узнать, значения заполняются правильно, а это не так, они на самом деле являются нулевыми. Этот обновленный метод выглядит следующим образом:
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
Player *info = [_fetchedResultsController objectAtIndexPath:indexPath];
playerPhotoCell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"playerCell" forIndexPath:indexPath];
cell.playerImage.image = [UIImage imageWithData:info.mugshot];
cell.playerLabel.text = info.forename;
if(info.mugshot){
NSLog(@"Player Image is of type %@", NSStringFromClass([info.mugshot class]));
}
cell.backgroundColor = [UIColor whiteColor];
return cell;
}
NSLog of info.mugshot не вызывается, так как он не выполняет условие. Однако, если вы перейдете и добавите нового игрока, а затем вернитесь к представлению viewcontroller в том же сеансе, NSLog сообщает, что образ игрока является типом NSconcreteMutableData и правильно заполняет ячейку вместе с правильным количеством пустых ячеек. Если вы закроете приложение и упустите его, вернитесь обратно, он вернет правильное количество пустых ячеек.
EDIT: Добавить код нового игрока (предупреждение: потенциально опасный код!;)
- (IBAction)saveBtn:(id)sender {
self.player = [Player alloc];
self.player.mugshot = UIImageJPEGRepresentation(_chosenImage, 1);
self.player.forename = fName.text;
self.player.surname = sName.text;
self.player.email = email.text;
self.player.mobNum = [NSNumber numberWithInteger:[mobNum.text integerValue]];
if(twitHandle){
self.player.twitter = twitHandle.text;
}
self.profile = [Profile alloc];
self.profile.position = position.text;
self.profile.type = _pressedBtnName;
self.profile.workRate = [NSNumber numberWithInt:(wrRating) ];
self.profile.stamina = [NSNumber numberWithInteger:(stRating)];
self.profile.skill = [NSNumber numberWithInteger:(skRating) ];
self.profile.finishing = [NSNumber numberWithInteger:(fiRating)];
self.profile.passing = [NSNumber numberWithInteger:(paRating)];
self.profile.strength = [NSNumber numberWithInteger:(strRating)];
NSEntityDescription *playerEntityDescription = [NSEntityDescription entityForName:@"Player" inManagedObjectContext:context];
NSManagedObject *newPlayer = [[NSManagedObject alloc] initWithEntity:playerEntityDescription insertIntoManagedObjectContext:context];
[newPlayer setValue:self.player.forename forKey:@"forename"];
[newPlayer setValue:self.player.surname forKey:@"surname"];
[newPlayer setValue:self.player.email forKey:@"email"];
[newPlayer setValue:self.player.mobNum forKey:@"mobNum"];
[newPlayer setValue:self.player.twitter forKey:@"twitter"];
[newPlayer setValue:self.player.mugshot forKey:@"mugshot"];
NSEntityDescription *pattrEntityDescription = [NSEntityDescription entityForName:@"Profile" inManagedObjectContext:context];
NSManagedObject *newPlayerAttr = [[NSManagedObject alloc] initWithEntity:pattrEntityDescription insertIntoManagedObjectContext:context];
[newPlayerAttr setValue:self.profile.position forKey:@"position"];
[newPlayerAttr setValue:self.profile.type forKey:@"type"];
[newPlayerAttr setValue:self.profile.workRate forKey:@"workRate"];
[newPlayerAttr setValue:self.profile.stamina forKey:@"stamina"];
[newPlayerAttr setValue:self.profile.skill forKey:@"skill"];
[newPlayerAttr setValue:self.profile.finishing forKey:@"finishing"];
[newPlayerAttr setValue:self.profile.passing forKey:@"passing"];
[newPlayerAttr setValue:self.profile.strength forKey:@"strength"];
[newPlayer setValue:newPlayerAttr forKey:@"profile"];
На данный момент, я понимаю, я не должен необходимо установить обратный как его определено в модели, но если я не с помощью следующей строки, я получил ошибку - опять плохо, но просто хотел, чтобы получить что-то работа
[newPlayerAttr setValue:newPlayer forKey:@"player"];
if (newPlayer.managedObjectContext != nil) {
NSError *error = nil;
if (![newPlayer.managedObjectContext save:&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.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
Объекты Player и profile - это только экземпляры тех классов, которые были созданы из соответствующих объектов в модели. Их файлы в основном содержат только свойство для каждого объекта атрибута
Запросов к БД SQLite позволяет предположить, что данные записываются правильно
Для информации, в моем cellforitematindexpath я положил в NSLog для вывода типа [_fetchedResultsController objectAtIndex : indexPath], и он вернулся с Player. Итак, на этой основе я не знаю, почему создание информации об экземпляре Player и ее настройка на нее тогда не работает, но свойства информации равны нулю.
EDIT: Я добавил запрос на выбор в свой делегат приложения и выполнил его в конце метода didFinishLaunchingWithOptions следующим образом:
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
// Update to handle the error appropriately.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
exit(-1); // Fail
}
NSLog(@"fetch count %@",[NSString stringWithFormat:@"%lu",(unsigned long)[self.fetchedResultsController.fetchedObjects count]]);
Player *ken = [self.fetchedResultsController.fetchedObjects firstObject];
NSLog(@"Surname %@",ken.surname);
извлечённый счетчик объектов сообщает 6, который является правильным. Однако следующая строка, которая пытается назначить первый объект fetchedObjects экземпляру Player под названием Ken, выдает вывод в следующей строке «Фамилия» (null), которая действительно просто чудесная *. Во всяком случае, возможно, мой код там неправильный, но кажется, что объект не устанавливается вообще не говоря уже об атрибутах, потому что я также сделал тест (не показан в фрагменте кода) объекта ken, например if (ken) {... который никогда не встречался. В любом случае будет кричать в подушку на некоторое время и, возможно, сделать всплакнуть
* сильно раздражает
self.fetchedResultsController = theFetchedResultsController; Эта строка должна быть _fetchedResultsController = theFetchedResultsController, используя self вы снова и снова вызываете - (NSFetchedResultsController *) fetchedResultsController. – Sandy
Привет Сэнди, спасибо за указание на это - я полностью пропустил ваш комментарий раньше, поэтому извиняюсь за то, что не ответил раньше. Я посмотрю на это и посмотрю, поможет ли это. Еще раз спасибо – Craigen
Если вы регистрируете значение объектов 'info' Player в вашей' cellForItemAtIndexPath', правильно ли заполнены свойства объектов (т.е. mugshot, forename)? – pbasdf