web-dev-qa-db-ja.com

CoreDataでフェッチされたプロパティを並べ替える方法

Core Data Documentation は、次のように述べています。

[fetched]プロパティに関連付けられたフェッチ要求には並べ替え順序を設定できるため、フェッチされたプロパティに順序を付けることができます。

Xcodeのデータモデルエディタでフェッチされたプロパティのソート記述子を指定するにはどうすればよいですか?関連するフィールドがどこにも見つかりません。これが何か違いを生むなら、私はiPhoneプラットフォーム用に開発しています。

グラフィカルモデルエディターでこれが不可能な場合、コード内のフェッチされたプロパティのフェッチ要求を変更して、並べ替え記述子を含めるにはどうすればよいですか?

20
Daniel Dickison

モデリングツールには、フェッチリクエストでソート記述子を設定する方法がないようです。

モデルをロードした後、永続ストアコーディネーターに関連付ける前に、ソート順を制御するフェッチされたプロパティの説明を見つけて、それらのフェッチ要求をソートのあるフェッチ要求に置き換えることができるはずです[1]。それらに設定された記述子。

[1]原則として、これは機能するはずです。実際には、私はそうしなかったか、それをテストしていません。

5
Jim Correia

実際にモデルのフェッチされたプロパティを取得し、それにソート記述子を追加できます(ここでもコードで)。これは、Core Dataを使用してテンプレートの1つを選択した場合に、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;
}
35
Tim Shadel

グラフィカルエディタでそれらを指定しません(私が知る限り)。

フェッチを行うコードでそれらを指定します。

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"];
13
mmc

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];
    }
}
5
rob5408

ただし、残念ながら、並べ替えの機能は多少制限されています。たとえば、少なくともSQLiteバッキングストアでは、数値を含むNSStringであるフィールドを取得して、数値で並べ替えることはできません。ただし、文字列でアルファベット順に並べ替えたり、数値として格納された値でのみ数値で並べ替えたりする限り、フェッチ要求に適用されるNSSortDescriptorは問題なく機能します。

0
Jeff Medcalf

単一のフェッチされたプロパティの場合、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

注:この例では、値を強制的にアンラップします。 実際のコードではオプションの値を考慮に入れてください!

0
leanne

これを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]];
}

EntityManagedObjectSubClassentityNamefetchedPropertyName、およびsortDescriptorKeyを独自のものに置き換えます。

0