gpt4 book ai didi

ios - 核心数据似乎获取了空对象

转载 作者:行者123 更新时间:2023-11-28 17:56:17 25 4
gpt4 key购买 nike

在我的iOS应用中,我试图通过核心数据在一个视图中将值保存到sqlite数据库,然后在另一个视图中检索。查看数据库,保存工作正常,对象位于数据库中,符合预期。如果然后转到我的收藏视图,结果将正确显示。但是,如果我很喜欢该应用程序并重新打开,则在检索时,收集视图将显示正确数量的单元格(行),但所有单元格都为空???
提取计数始终返回0,但是已经设置了命令行args以查看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;


}

并通过命令行args工具为sql生成以下日志:

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.


如您所见,它似乎在运行两个查询,我觉得很奇怪,但是作为菜鸟,我不知道这是否是它的工作方式。它似乎暗示的是,尽管读取计数报告为0,但它已读取了4行,这就是那里的全部内容。

如果有帮助,以下是我的集合视图数据源方法:

#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;
}


香港专业教育学院可能犯了一些明显的和基本的错误,但如果我能发现它们或找到任何答案,我该死。如果有人可以帮助我指出正确的方向,我将不胜感激。谢谢阅读

编辑:感谢pbasdf指出了我计算调用次数的错误,我将这段代码移到了适当的位置,并且确实返回了正确数量的对象

正如后来承诺的那样,我的playerPhotoCell只是一个脚本,在h文件中具有两个属性,可以充当图像视图的出口,并充当我添加到情节提要中单元格的标签。 .m文件中没有任何方法,因为我认为我的viewController代码可以简单地引用出口并设置它们的值-实际上,如果您在与保存单元格正确填充相同的会话中进行查看,这似乎可以正常工作-关闭并重新加载应用程序时会出现问题-加载了正确数量的单元格,但所有单元格都只有白色背景且没有任何信息

进一步编辑:
如建议的那样,我向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;
}


不会调用info.mugshot的NSLog,因为它使条件失败。但是,如果您随后在其中添加新播放器,然后返回同一会话中的viewcontroller视图,则NSLog会报告播放器图像为NSconcreteMutableData类型,并正确填充单元格以及正确数量的空白单元格。如果您关闭该应用程序并关闭然后再返回,它只会返回正确数量的空单元格。

编辑:添加新的播放器代码(警告:潜在危险代码!

- (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和配置文件对象只是从模型中的相应实体创建的那些类的实例。他们的文件基本上只包含每个Entity属性的一个属性

查询sqlite db表明数据已正确写入

有关信息,我在cellforitematindexpath中放入了一个NSLog来输出[_fetchedResultsController objectAtIndex:indexPath]的类型,然后随播放器一起返回。因此,在此基础上,不知道为什么创建Player实例信息并将其设置为该信息不起作用,但是info的属性为null

编辑:
我已将提取请求添加到我的应用程序委托中,并在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第一个对象分配给名为Ken的Player实例的下一行在'Surname(null)'的下一行上产生输出,这实际上简直是惊人的*。无论如何,也许我的代码在那里是错误的,但似乎根本没有设置对象,更不用说属性了,因为我还对ken对象进行了测试(未在代码段中显示),例如if(ken){...从来没有遇到过。无论如何都会在枕头上尖叫一会儿,也许会哭一点

*非常烦人

最佳答案

您需要告诉获取的结果控制器实际执行获取。在fetchedResultsController行中的return _fetchedResultsController;代码中插入以下内容:

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


编辑

我相信您的问题可能出在保存对象的代码中。如注释中所述,如果不立即使用初始化程序,则不能使用 alloc。对于NSManagedObjects(和子类),指定的初始化程序为 initWithEntity:insertIntoManagedObjectContext:。但是我想您不希望将 self.playerself.profile添加到数据库中,就像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();
}
}
}

关于ios - 核心数据似乎获取了空对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28422074/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com