【问题标题】:iOS - CoreData fault causing null valuesiOS - CoreData 错误导致空值
【发布时间】:2013-09-17 19:48:02
【问题描述】:

当我第一次填充视图时,我会这样做:

self.cats = [[DataManager sharedManager] getCatsFromCoreData]; //cats is an NSArray property (strong)
for (Cat* cat in self.cats)
    {
        CatThumbnailView *thumb = [CatThumbnailView catThumbnailView];
        thumb.cat = cat;

        UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(thumbnailTapped:)];
        [thumb addGestureRecognizer:tap];
        [thumb setText:[cat.name uppercaseString]];

        ...


        [self.someScrollview addSubview:thumb];
        yPos += thumb.frame.size.height + spacing;
    }

DataManager 的 get 方法如下所示:

- (NSArray*)getCatsFromCoreData
{

    NSManagedObjectContext *context = [[CoreDataController sharedController] managedObjectContext];

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:[NSEntityDescription entityForName:@"Cats" inManagedObjectContext:context]];
    [request setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"order" ascending:YES]]];


    NSError *error = nil;
    NSArray *fetchedCats = [context executeFetchRequest:request error:&error];


    if (fetchedCats.count > 0) {
        return fetchedCats;
    }

    return nil;
}

一切正常。视图已填充。缩略图点击方法如下所示:

- (void)thumbnailTapped:(UITapGestureRecognizer*)tap
{

    CatThumbnailView* thumb = (CatThumbnailView*)tap.view;

    DLog(@"cat %@", thumb.cat);
    DLog(@"cat id: %@", thumb.cat.cat_id);

    //do stuff here with the cat data

}

问题是,有时当我点击猫的缩略图时,我会看到:

cat <Cat: 0x7fa450> (entity: Cat; id: 0x7b71f0 <x-coredata://7C904BD2-16AA-486D-8D1B-C2D0ABCCB6D4/Cat/p1> ; data: <fault>)
cat id: (null)

因为 cat id 为 null,所以当我尝试对其进行操作时,应用程序会崩溃。

所以当我第一次从 CoreData 检索 cat 对象并布置视图时,cat id 永远不会为空。当我稍后点击其中一个缩略图时,数据已成为错误,因此当我访问 cat_id 属性时,它为空。 CatThumbnailView 保留了 Cat 实体:

@property (nonatomic, strong) Cat* cat;

为什么会发生这种情况,我该怎么办?

*注意 - 并非每次我点击缩略图时都会发生这种情况。我会说它发生在 10-20% 的时间里。其他 80-90% 的时间数据不是故障。为什么????

【问题讨论】:

  • 核心日期“错误”只是一个占位符对象,访问属性会“触发错误”,这意味着实际内容是从底层存储中获取的。 - 所以“故障”不是错误的指标,也不会“导致空值”。
  • 谢谢,但这并不能真正解决这个问题。当应用程序正常工作时,而不是将实体记录为故障,它会记录具有所有正确值的实际实体,当然在这种情况下猫 ID 是有效的。
  • 我只是想解释一下,你的说法“数据已成为故障,所以当我访问cat_id属性时,它是null”是不正确的。仅此而已。
  • [[CoreDataController sharedController] managedObjectContext] 是否返回一次性上下文,或者该上下文是否被经理强烈持有?此上下文是否在任何时间点重置?
  • 我遇到了同样的问题,在应用程序内部进行大量导航后很少发生崩溃。你解决了这个问题吗?

标签: ios core-data uiview fault


【解决方案1】:

我知道这有点老了,但最可能的解释是你的 Cat 类的实现看起来像这样:

@implementation Cat
@synthesise cat_id = _cat_id;
...
@end

什么时候应该是这样的:

@implementation Cat
@dynamic cat_id;
...
@end

我自己也犯了这个错误,所以分享一下,希望它能为下一个人节省一点时间!

【讨论】:

  • 非常感谢!这让我很困惑为什么只有一个属性返回 nil 并且即使我保存了上下文也没有解决错误。我将一个瞬态属性移到模型中,而没有将其更改为@dynamic。呵呵。
  • 大声笑,这个问题我已经过了 3 天。谁能解释为什么会这样? @synthesise 和 @dynamic 有什么区别?
  • 甜蜜!在找到您的回复之前,我只花了几个小时进行故障排除。
【解决方案2】:

在需要访问该对象的实际值之前,核心数据不会返回完整的对象。在此之前,您返回的每个对象都将是一个“错误”。

您可以在Fetch Request 上使用[request setReturnsObjectsAsFaults:NO] 来强制获取完整对象,但在大多数情况下这不是必需的


在您的情况下,我怀疑 manageObjectContext 在获取对象时是如何达到无效状态或不可用的。

而不是将manageObjectContext 的范围限制在您的方法中 仅限getCatsFromCoreData,声明manageObjectContext 控制器级别,以便它在实际时可用 获取对象。

附注确保manageObjectContext 在实际获取对象时可用。

希望这会对你有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-22
    • 2011-06-25
    • 1970-01-01
    • 2015-10-02
    • 1970-01-01
    相关资源
    最近更新 更多