Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/108.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 核心数据部分NameKeyPath与关系属性性能问题_Ios_Objective C_Uitableview_Core Data_Nsfetchedresultscontroller - Fatal编程技术网

Ios 核心数据部分NameKeyPath与关系属性性能问题

Ios 核心数据部分NameKeyPath与关系属性性能问题,ios,objective-c,uitableview,core-data,nsfetchedresultscontroller,Ios,Objective C,Uitableview,Core Data,Nsfetchedresultscontroller,我有一个包含三个实体的核心数据模型: 人,组,照片,它们之间的关系如下: Person根据我的经验,实现目标的一种方法是对模型进行非规范化。特别是,您可以在Person实体中添加group属性,并将该属性用作sectionNameKeyPath。因此,当您创建一个人时,您还应该传递它所属的组 此反规范化过程是正确的,因为它允许您避免获取相关的组对象,因为这不是必需的。缺点可能是,如果更改组的名称,则与该名称关联的所有人员都必须更改,相反,您可能会有不正确的值 这里的关键方面如下。您需要记住,核

我有一个包含三个实体的核心数据模型:
照片
,它们之间的关系如下:


  • Person根据我的经验,实现目标的一种方法是对模型进行非规范化。特别是,您可以在
    Person
    实体中添加
    group
    属性,并将该属性用作
    sectionNameKeyPath
    。因此,当您创建一个
    人时,您还应该传递它所属的组

    此反规范化过程是正确的,因为它允许您避免获取相关的
    对象,因为这不是必需的。缺点可能是,如果更改组的名称,则与该名称关联的所有人员都必须更改,相反,您可能会有不正确的值

    这里的关键方面如下。您需要记住,核心数据不是 关系数据库。该模型不应设计为数据库模式,在这种模式下可以进行规范化,但应从数据如何在用户界面中呈现和使用的角度进行设计

    编辑1

    我听不懂你的评论,你能解释清楚吗

    但我发现非常有趣的是,即使应用程序是 在模拟器中执行完整的前端抓取,应用程序加载到 设备上的900毫秒(5000个对象),尽管模拟器 加载速度要慢得多

    无论如何,我有兴趣了解您的
    照片
    实体的详细信息。如果预取照片,可能会影响整体执行

    是否需要在表视图中预取
    照片
    ?它们是拇指吗(小照片)?还是普通图像?你利用了吗

    个人
    实体添加附加属性(例如
    )可能不是问题。当
    对象的
    名称
    发生更改时更新该属性的值如果在后台执行该操作,则不会出现问题。此外,从iOS 8开始,您可以进行批更新,如中所述。

    这是您声明的目标:“我需要按照关系实体组、名称属性和NSFetchResultsController将Person对象分组,以便在滚动时小批量执行抓取,而不是像现在这样提前执行。” 答案有点复杂,主要是因为
    NSFetchedResultsController
    如何构建节,以及它如何影响抓取行为

    TL;博士要更改此行为,您需要更改NSFetchedResultsController构建节的方式。 发生了什么事? 当
    NSFetchedResultsController
    收到带有分页(fetchLimit和/或fetchBatchSize)的获取请求时,会发生几种情况

    如果未指定任何
    sectionNameKeyPath
    ,则它将完全按照您的预期执行。fetch返回一个结果的代理数组,第一个fetchSize数量的项包含“real”对象。因此,例如,如果将
    setFetchBatchSize
    设置为2,并且谓词匹配存储中的10项,则结果包含前两个对象。其他对象将在访问时单独获取。这提供了平滑的分页响应体验

    但是,当指定了
    sectionNameKeyPath
    时,获取结果控制器必须执行更多操作。要计算截面,它需要访问结果中所有对象上的关键路径。它列举了我们示例中结果中的10项。前两个已被提取。其他8个将在枚举期间获取,以获取构建节信息所需的键路径值。如果获取请求的结果很多,那么这可能会非常低效。与此功能相关的公共bug有很多:

    。。。还有其他几个。仔细想想,这是有道理的。要构建
    NSFetchedResultsSectionInfo
    对象,需要FetchedResultsSectionInfo控制器查看
    sectionNameKeyPath
    结果中的每个值,将它们聚合到值的唯一并集,并使用该信息创建正确数量的
    NSFetchedResultsSectionInfo
    对象,设置名称和索引标题,知道一个部分包含的结果中有多少对象,等等。要处理一般用例,没有办法解决这个问题。记住这一点,你的仪器痕迹可能会更有意义

    你怎么能改变这个? 您可以尝试构建自己的
    NSFetchedResultsController
    ,它为构建
    NSFetchedResultsSectionInf
    o对象提供了一种替代策略,但您可能会遇到一些相同的问题。例如,如果您正在使用现有的fetchedObjects功能访问fetch结果的成员,则在访问出错的对象时将遇到相同的行为。您的实现将需要一个处理此问题的策略(这是可行的,但取决于您的需求)

    哦,天啊,不。那什么临时的黑客程序呢?它只会让它表现得更好一点,但不能解决问题? 改变数据模型不会改变上述行为,但会略微改变性能影响。批处理更新不会对该行为产生任何显著影响,事实上,它不会很好地与“获取结果”控制器配合使用。但是,将
    relationshipkypathsforprefetching
    设置为包含您的“组”关系可能对您更有用,这可能会显著改善抓取和出错行为。另一种策略可能是在尝试使用“获取结果控制器”(fetched results controller)之前执行另一次获取以批处理这些对象,这将以更高效的方式填充内存缓存中不同级别的核心数据
    - (NSFetchedResultsController *)fetchedResultsController {
    
        if (_fetchedResultsController) {
            return _fetchedResultsController;
        }
    
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
        NSEntityDescription *entity = [NSEntityDescription entityForName:[Person description]
                                                  inManagedObjectContext:self.managedObjectContext];
    
        [fetchRequest setEntity:entity];
    
        // Specify how the fetched objects should be sorted
        NSSortDescriptor *groupSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"group.name"
                                                                            ascending:YES];
    
        NSSortDescriptor *personSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthName"
                                                                             ascending:YES
                                                                              selector:@selector(localizedStandardCompare:)];
    
    
        [fetchRequest setSortDescriptors:[NSArray arrayWithObjects:groupSortDescriptor, personSortDescriptor, nil]];
    
        [fetchRequest setRelationshipKeyPathsForPrefetching:@[@"group", @"photo"]];
        [fetchRequest setFetchBatchSize:20];
    
        NSError *error = nil;
        NSArray *fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
    
        if (fetchedObjects == nil) {
            NSLog(@"Error Fetching: %@", error);
        }
    
        _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                                                        managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"group.name" cacheName:@"masterCache"];
    
        _fetchedResultsController.delegate = self;
    
        return _fetchedResultsController;
    }