2015-02-10 6 views
1

В моем приложении 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) {... который никогда не встречался. В любом случае будет кричать в подушку на некоторое время и, возможно, сделать всплакнуть

* сильно раздражает

+0

self.fetchedResultsController = theFetchedResultsController; Эта строка должна быть _fetchedResultsController = theFetchedResultsController, используя self вы снова и снова вызываете - (NSFetchedResultsController *) fetchedResultsController. – Sandy

+0

Привет Сэнди, спасибо за указание на это - я полностью пропустил ваш комментарий раньше, поэтому извиняюсь за то, что не ответил раньше. Я посмотрю на это и посмотрю, поможет ли это. Еще раз спасибо – Craigen

+0

Если вы регистрируете значение объектов 'info' Player в вашей' cellForItemAtIndexPath', правильно ли заполнены свойства объектов (т.е. mugshot, forename)? – pbasdf

ответ

-2

в конце концов я нашел решение этой проблемы, и это было то, что класс игрока не правильно инициализирует свойства и т.д .. так что, когда я создавал экземпляр этого класса, свойства не были инициализированы и поэтому были нулевыми. Я добавил метод инициализации файла Player.m и удалил операторы синтеза, и все вышло в жизнь. Я отправлю метод, который я использовал позже.

Огромное спасибо pbasdf за помощь в этом, без чего я бы не получил ответа - это сообщество.

0

Вы должны сказать сгружен контроллер результаты на самом деле выполнять выборки. Вставьте что-то подобное в fetchedResultsController коде, как раз перед return _fetchedResultsController; линии:

NSError *error = nil; 
if (![_fetchedResultsController performFetch:&error]) { 
    NSLog(@"Fetch error %@, %@", error, [error userInfo]); 
    abort(); 
} 

EDIT

Я считаю, что ваши проблемы могут лежать в коде, который сохраняет объекты. Как указано в комментариях, вы не можете использовать alloc без немедленного использования инициализатора. Для NSManagedObjects (и подклассов) назначенный инициализатор равен initWithEntity:insertIntoManagedObjectContext:. Но я предполагаю, что вы не хотите, чтобы self.player и self.profile были добавлены в базу данных AS WELL AS newPlayer и newPlayerProfile. Поэтому я предлагаю переписывания следующим образом:

- (IBAction)saveBtn:(id)sender { 
    NSEntityDescription *playerEntityDescription = [NSEntityDescription entityForName:@"Player" inManagedObjectContext:context]; 
    NSManagedObject *newPlayer = [[NSManagedObject alloc] initWithEntity:playerEntityDescription insertIntoManagedObjectContext:context]; 
    [newPlayer setValue:fName.text forKey:@"forename"]; 
    [newPlayer setValue:sName.text forKey:@"surname"]; 
    [newPlayer setValue:email.text forKey:@"email"]; 
    [newPlayer setValue:[NSNumber numberWithInteger:[mobNum.text integerValue]] forKey:@"mobNum"]; 
    if(twitHandle){ 
     [newPlayer setValue:twitHandle.text forKey:@"twitter"]; 
    } 
    [newPlayer setValue:UIImageJPEGRepresentation(_chosenImage, 1) forKey:@"mugshot"]; 

    NSEntityDescription *pattrEntityDescription = [NSEntityDescription entityForName:@"Profile" inManagedObjectContext:context]; 
    NSManagedObject *newPlayerAttr = [[NSManagedObject alloc] initWithEntity:pattrEntityDescription insertIntoManagedObjectContext:context]; 
    [newPlayerAttr setValue:position.text forKey:@"position"]; 
    [newPlayerAttr setValue:_pressedBtnName forKey:@"type"]; 
    [newPlayerAttr setValue:[NSNumber numberWithInt:(wrRating)] forKey:@"workRate"]; 
    [newPlayerAttr setValue:[NSNumber numberWithInteger:(stRating)] forKey:@"stamina"]; 
    [newPlayerAttr setValue:[NSNumber numberWithInteger:(skRating)] forKey:@"skill"]; 
    [newPlayerAttr setValue:[NSNumber numberWithInteger:(fiRating)] forKey:@"finishing"]; 
    [newPlayerAttr setValue:[NSNumber numberWithInteger:(paRating)] forKey:@"passing"]; 
    [newPlayerAttr setValue:[NSNumber numberWithInteger:(strRating)] forKey:@"strength"]; 

    [newPlayer setValue:newPlayerAttr forKey:@"profile"]; 
    // You are right, you shouldn't need the next line 
    // [newPlayerAttr setValue:newPlayer forKey:@"player"]; 

    // Not sure whether self.profile and self.player are used elsewhere, 
    // So set them to the newly created objects: 
    self.player = newPlayer; 
    self.profile = newPlayerAttr; 

    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(); 
     } 
    } 
} 
+0

Ах, извините, мой плохой, выполнить код выборки в моем методе viewDidLoad файла collectionViewController.m - извинения, я должен был указать, что – Craigen

+0

ОК. В этом случае NSLog в вашем коде fetchedResultController происходит до исполненияFetch, что объясняет, почему он возвращает ноль. – pbasdf

+0

ha да конечно! Блин, черт побери! Наверное, я переведу код и сначала проверил количество выборки, прежде чем продолжить, чтобы больше не тратить время на любое время, так как это может дать дополнительные сведения о проблеме. Спасибо за ваши ответы, очень благодарен – Craigen

0

Комментарий от Craigen's Feb 10'15 помог мне (Core Data noob) после многих бесплодных часов увидеть нулевые значения в ячейках или просто отсутствующие строки и задаться вопросом, как я мог бы подсчитать количество строк из выборки, которая казалась правильной, но никогда не соответствовала мой NSFetchedResultsSectionInfo numberOfObjects. Изменение имени cacheName NSFetchedResultsController для nil неожиданно привело мои недостающие строки в tableview, и все это, в конечном счете, имело смысл.

Смежные вопросы