【问题标题】:Core Data: does a fetch have to make a trip to persistent store?核心数据:获取是否必须访问持久存储?
【发布时间】:2012-12-12 05:42:42
【问题描述】:

假设我这样做:

NSManagedObjectContext *context = #a managed object context";
NSString *entityName = #an entity name#;
NSFetchRequest *requestForAll = [NSFetchRequest requestWithEntityName:entityName];
NSArray *allObj = [context executeFetchRequest:requestForAll];

for (NSString *name in allNamesArray){
    NSFetchRequest *requestForOne = [NSFetchRequest requestWithEntityName:entityName];
    requestForOne.predicate = [NSPredicate predicateWithFormat:@"name == %@",name];
    NSArray *ObjsWithName = [context executeFetchRequest:requestForOne];
    #do some work with the obj#
}

循环中的 fetch 是否每次都会导致访问持久存储?或者那些提取只会在 coredata 的行缓存中执行?

编辑 我写了一段测试代码: 您需要创建一个名为“Person”的核心数据实体,它应该有一个名为“name”的属性,它是字符串类型。

使用此代码填充一些数据:

self.array = @[@"alkjsdfkllaksjdf",@"asldjflkajdklsfjlk;aj",@"aflakjsdl;kfjalksdjfklajkldhkl;aj",@"aljdfkljalksdjfl;j" ,@"flajdl;kfjaklsdjflk;j",@"akldsjfklajdslkf",@"alkdjfkljaklsdjflkaj",@"alsdjflkajsdflj",@"adlkfjlkajsdfkljkla",@"alkdjfklajslkdfj"];

NSString *firstRunKey = @"oh its first run!";
NSString *firstRun = [[NSUserDefaults standardUserDefaults] objectForKey:firstRunKey];
if (!firstRun) {
    for (NSString *name in self.array) {
        Person *p = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:self.managedObjectContext];
        p.name = name;
    }
}
[self.managedObjectContext save];
[[NSUserDefaults standardUserDefaults] setObject:firstRunKey forKey:firstRunKey];
[[NSUserDefaults standardUserDefaults] synchronize];

分析这两种方法,您会发现 usingCoreData 比 usingFilterArray 花费更多时间!

static int caseCount = 1000;
-(void)usingCoreData
{
    NSLog(@"core data");
    NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Person"];
    NSArray *allPersons = [self.managedObjectContext executeFetchRequest:request error:nil];

    for (int i = 0; i < caseCount; i++){
        for (NSString *name in self.array) {
            request.predicate = [NSPredicate predicateWithFormat:@"name == %@",name];
            NSArray *result = [self.managedObjectContext executeFetchRequest:request error:nil];
        }
    }
}

-(void)usingFilterArray
{
    NSLog(@"filter array");
    NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Person"];
    NSArray *allPersons = [self.managedObjectContext executeFetchRequest:request error:nil];

    for (int i = 0; i < caseCount; i++){
        for (NSString *name in self.array) {
            NSArray *array = [allPersons filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"name == %@",name]];
        }
    }
}

【问题讨论】:

    标签: iphone objective-c ios core-data


    【解决方案1】:

    我想我需要自己回答我的问题。

    我测试了一下发现,每次执行fetch,core data都会把你的NSFetchRequest翻译成SQL命令并调用数据库查询,查询结果首先是NSManagedObjectIDs,缓存是用来从NSManagedObjectID中获取NSManagedObject的。

    总之,它缓存对象,但不缓存查询结果。

    这意味着您执行相同的 NSFetchRequest 10 次,它将查询您的持久存储 10 次,尽管您将获得 10 次相同的结果。所以在这种情况下,在内存中过滤数组会比获取更好。

    【讨论】:

      【解决方案2】:

      获取将来自指定的缓存(如果可用)。

      编辑: 这是一个很棒的教程的链接,该教程展示了如何设置使用缓存的NSFetchedResultsController

      http://www.raywenderlich.com/?p=999

      【讨论】:

      • 所谓常识的文档……不然缓存是干什么用的?好吧,如果您愿意,您可以确认。文章提到了一种打开所有 SQL 命令以查看实际情况的方法。
      • @borrrden 这不是很好
      • 不,不是……但对我来说,要求“一份说明这一点的文件”就像是在说“我不相信你的回答”
      • @borrrden 听起来他在寻找证据,你知道,这就是计算机科学的运作方式,而一般的科学,也是基于证据的。但我想你已经知道了……
      • @borrrden 我曾经认为核心数据将在缓存中过滤,而不是访问持久存储。但是我发现使用带有谓词的 fetch 比在内存中使用相同的谓词过滤数组要慢得多(在基准测试时我没有在核心数据中插入/更新/删除任何新行),这就是我在这里问的原因。另外为什么我不使用 NSFetchedResultController 是因为它是异步的,我不能使用是我当前的问题。
      猜你喜欢
      • 2012-06-17
      • 1970-01-01
      • 2012-12-20
      • 2011-08-11
      • 1970-01-01
      • 1970-01-01
      • 2015-02-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多