【问题标题】:How to sort Core Data fetched properties如何对核心数据获取的属性进行排序
【发布时间】:2010-11-07 11:46:49
【问题描述】:

Core Data Documentation 声明:

与 [fetched] 属性关联的 fetch 请求可以具有排序顺序,因此可以对 fetched 属性进行排序。

如何在 Xcode 的数据模型编辑器中为 fetched 属性指定排序描述符?我在任何地方都找不到相关领域。我正在为 iPhone 平台开发,如果这有什么不同的话。

如果通过图形模型编辑器无法做到这一点,我该如何在代码中修改 fetched 属性的 fetch 请求,使其具有排序描述符?

【问题讨论】:

    标签: iphone xcode sorting core-data fetched-property


    【解决方案1】:

    对于单个提取的属性,Swift 4、Xcode 9.4:

    // retrieve the fetched property's fetch request    
    let fetchedPropertyRequest = (modelName.entitiesByName["entityName"]!.propertiesByName["fetchedPropertyName"] as! NSFetchedPropertyDescription).fetchRequest
    
    // set up the sort descriptors
    let sortDescriptors = [NSSortDescriptor(key: "keyName", ascending: true)]
    
    // add the sort descriptors to the fetch request
    fetchedPropertyRequest!.sortDescriptors = sortDescriptors
    

    这也是 loooonnnnnnggggggg 的方式:

    // retrieve the fetched property's fetch request
    let theEntityDescription: NSEntityDescription = modelName.entitiesByName["entityName"]!
    let theFetchedPropertyDescription = theEntityDescription.propertiesByName["fetchedPropertyName"]! as! NSFetchedPropertyDescription
    let theFetchedPropertyRequest = theFetchedPropertyDescription.fetchRequest
    
    // set up the sort descriptors
    let sortDescriptor1 = NSSortDescriptor(key: "keyName", ascending: true)
    let theSortDescriptors = [sortDescriptor1]
    
    // add the sort descriptors to the fetch request
    theFetchedPropertyRequest!.sortDescriptors = theSortDescriptors
    

    注意:对于这个例子,我强制解包值。 确保在实际代码中考虑可选值!

    【讨论】:

      【解决方案2】:

      使用 Tim Shadel 的最佳答案,我添加了按 NSManagedObject 子类排序...

      ...在 Tier.m 中(这是一个 NSManagedObject 子类)...

      + (void)initialize
      {
          if(self == [Tier class])
          {
              NSFetchedPropertyDescription *displayLessonPropertyDescription = [[[Tier entityDescription] propertiesByName] objectForKey:@"displayLesson"];
              NSFetchRequest *fetchRequest = [displayLessonPropertyDescription fetchRequest];
      
              NSSortDescriptor *sortByName = [[NSSortDescriptor alloc] initWithKey:@"displayOrder" ascending:YES];
             [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortByName]];
              [sortByName release];
          }
      }
      

      【讨论】:

      • -[Tier entityDescription] 定义在哪里?!
      • 啊,我在这种情况下使用的是 RestKit,它有很多方便的方法。查看他们的 NSManagedObject+ActiveRecord 类别。
      • 不知道为什么@AndyOS 的编辑被拒绝了,我的代码肯定有错误。
      【解决方案3】:

      把它放到你的NSManagedObject 子类中:

      + (void)initialize
      {
          if (self != [EntityManagedObjectSubClass class]) return;
          NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
          NSEntityDescription *entityDescription = [managedObjectModel entitiesByName][@"entityName"];
          NSFetchedPropertyDescription *fetchedPropertyDescription = [entityDescription propertiesByName][@"fetchedPropertyName"];
          NSFetchRequest *fetchRequest = [fetchedPropertyDescription fetchRequest];
          NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"sortDescriptorKey" ascending:YES];
          [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
      }
      

      用你自己的东西替换EntityManagedObjectSubClassentityNamefetchedPropertyNamesortDescriptorKey

      【讨论】:

        【解决方案4】:

        Jeff,如果字符串是右对齐的,你可以对字符串进行排序; “123”>“23”等等。但是 iirc ascii 空格在数字之后,如果是这样,那么您要做的就是创建一个动态属性,它是一个 NSNumber(它支持 compare: 方法),并使用 numberFromString: 方法从字符串中生成一个数字。然后您可以指定排序中的数字字段。在界面中:

        @property NSString *stringIsaNumber; // in the data model
        @property NSNumber *number;
        

        在实施中:

        @dynamic stringIsaNumber; 
        - (NSNumber *) number ;
        { return [self.stringIsaNumber numberFromString]; }
        - (void) setNumber:(NSNumber *)value;
        { self.stringIsaNumber = [NSString stringWithFormat:@"%5i",value) }
        

        ps 请原谅编码错误,这是我的想法。

        【讨论】:

          【解决方案5】:

          您实际上可以获取模型获取的属性并将排序描述符添加到它(再次,在代码中)。如果您选择具有 Core Data 的模板之一,我会在 XCode 在您的 AppDelegate 中生成的标准方法中执行此操作:

          顺便说一句。这会对数据模型中所有模型的所有获取的属性进行排序。你可以对它进行幻想和适应,但这是处理对 7 个单独模型进行排序的最简洁的方法,每个模型都获取了需要按名称排序的属性。效果很好。

          /**
           Returns the managed object model for the application.
           If the model doesn't already exist, it is created by merging all of the models found in the application bundle.
           */
          - (NSManagedObjectModel *)managedObjectModel {
          
              if (managedObjectModel != nil) {
                  return managedObjectModel;
              }
              managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];    
          
              // Find the fetched properties, and make them sorted...
              for (NSEntityDescription *entity in [managedObjectModel entities]) {
                  for (NSPropertyDescription *property in [entity properties]) {
                      if ([property isKindOfClass:[NSFetchedPropertyDescription class]]) {
                          NSFetchedPropertyDescription *fetchedProperty = (NSFetchedPropertyDescription *)property;
                          NSFetchRequest *fetchRequest = [fetchedProperty fetchRequest];
          
                          // Only sort by name if the destination entity actually has a "name" field
                          if ([[[[fetchRequest entity] propertiesByName] allKeys] containsObject:@"name"]) {
                              NSSortDescriptor *sortByName = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
                              [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortByName]];
                              [sortByName release];
                          }
                      }
                  }
              }
          
              return managedObjectModel;
          }
          

          【讨论】:

          • 此外,键值编码也可以对此有所帮助,例如:[managedObjectModel setValue:sortDescriptorArray forKeyPath:@"entitiesByName.EntityName.propertiesByName.fetchPropertyName.fetchRequest.sortDescriptors"];
          【解决方案6】:

          遗憾的是,排序的能力有些受限。例如,您不能获取一个包含数字的 NSString 字段,并对其进行数字排序,至少不能使用 SQLite 后备存储。但是,只要您按字母顺序对字符串进行排序,仅对存储为数字的值进行数字排序等等,应用于获取请求的 NSSortDescriptor 就可以正常工作。

          【讨论】:

          • 你可以编写更复杂的排序方法,使用 NSSortDescriptor 的 initWithKey:ascending:selector:
          【解决方案7】:

          您没有在图形编辑器中指定它们(据我所知)。

          您在进行提取的代码中指定它们。

          NSFetchRequest* request = [[NSFetchRequest alloc] init];
          NSEntityDescription* entity = [NSEntityDescription entityForName:@"whatYouAreLookingFor"
              inManagedObjectContext:self.managedObjectContext];
          [request setEntity:entity];
          
          // here's where you specify the sort
          NSSortDescriptor* sortDescriptor = [[NSSortDescriptor alloc]
                                          initWithKey:@"name" ascending:YES];
          NSArray* sortDescriptors = [[[NSArray alloc] initWithObjects: sortDescriptor, nil] autorelease];
          [request setSortDescriptors:sortDescriptors];
          [sortDescriptor release];
          
          fetchedResultsController = [[NSFetchedResultsController alloc]
                         initWithFetchRequest:request
                         managedObjectContext:self.managedObjectContext
                           sectionNameKeyPath:nil
                                    cacheName:@"myCache"];
          

          【讨论】:

          • 这在上面是正确的。您必须添加 NSSortDescriptor 您不能在数据模型中指定它抱歉。是的,它冗长,但这正是我在我的核心数据应用程序中所做的。
          • 以上对于正常的获取请求来说是可以的,但与问题无关,这是关于获取的属性及其排序的问题。
          【解决方案8】:

          建模工具似乎无法在获取请求上设置排序描述符。

          应该有可能[1] 在加载模型之后但在将其与持久存储协调器关联之前,找到要控制其排序顺序的提取属性描述,并将其提取请求替换为提取请求设置了排序描述符。

          [1] 原则上这应该可行。在实践中,我没有这样做或测试过。

          【讨论】:

          • 建模工具没有这个功能太可惜了——似乎它在很大程度上削弱了能够在工具中指定获取请求的实用性。
          • 这个问题提供了一个以编程方式创建 NSFetchedPropertyDescription 并将其添加到 NSManagedObjectModel 的示例:stackoverflow.com/questions/5638364/…
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-06-10
          • 1970-01-01
          • 2015-04-24
          • 1970-01-01
          相关资源
          最近更新 更多