1

アドバイスが必要です。私はコアデータにかなり慣れていません。

原則として正常に動作するコアデータモデルがあります。エンティティ「RoomType」があります。このエンティティには、String型の属性が1つだけあり、エンティティ「Room」(逆は1つの関係)に対する1つの関係(多く)があります。関係は関係ありません。私を夢中にさせるのは文字列とsortDescriptorです。

データベースの内容は英語です。このテーブルは、アプリのインストール時に動的に入力されるセットアップテーブルであり、ユーザーが変更することはありません。ドイツ語と第3言語の場合、このデータを翻訳する必要があります。私はその目的でNSLocalizedStringマクロを使用していますが、変換された値でデータを並べ替える以外は、うまく機能しています。

(将来のリリースでは、ユーザーがレコードを追加できるようにします。ただし、手動で追加したレコードは翻訳する必要はありません。)

これは自動的に生成されたRoomType.hです。

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@class Room;

@interface RoomType : NSManagedObject

@property (nonatomic, retain) NSString * typeName;
@property (nonatomic, retain) NSSet *rooms;
@end

@interface RoomType (CoreDataGeneratedAccessors)

- (void)addRoomsObject:(Room *)value;
- (void)removeRoomsObject:(Room *)value;
- (void)addRooms:(NSSet *)values;
- (void)removeRooms:(NSSet *)values;

@end

珍しいことは何もないと思います。

これは、私のViewController内のfetchedResultsControllergetterメソッドです。

- (NSFetchedResultsController *)fetchedResultsController
{
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.

    self.managedObjectContext = [(AppDelegate*) [[UIApplication sharedApplication] delegate] managedObjectContext];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"RoomType" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:20];

    // Edit the sort key as appropriate.
    NSSortDescriptor *sortDescriptor;
    sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"typeName" ascending:YES];
    [fetchRequest setSortDescriptors: @[sortDescriptor]];

    // Set the predicate // No predicate because we want to fetch all items
    //NSPredicate *predicate =
    //[NSPredicate predicateWithFormat:@"suite == %@", self.detailItem];
    //[fetchRequest setPredicate:predicate];

    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Suite"];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    NSError *error = nil;
    if (![self.fetchedResultsController performFetch:&error]) {
        // Replace this implementation with code to handle the error appropriately.
        // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return _fetchedResultsController;
}

データはピッカーに送られます:

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView {

    return 1;
}

- (NSInteger)pickerView:(UIPickerView *)thePickerView numberOfRowsInComponent:(NSInteger)component {

    int anzahl = [[self.fetchedResultsController fetchedObjects] count];
    return anzahl;
}

- (NSString *)pickerView:(UIPickerView *)thePickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {

    NSManagedObject *object = [[self.fetchedResultsController fetchedObjects] objectAtIndex:row];

    RoomType    *roomType   = (RoomType*) object;
    NSLog(@"%@ - %@", roomType.typeName, NSLocalizedString(roomType.typeName, @"Room-Type"));

    return NSLocalizedString(roomType.typeName, @"Room-Type");  // <-- HERE COMES THE TRANSLATION!
}

- (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {

    Room *theRoom = (Room*) [self detailItem];

    //Ignore the component cause there is only one.
    theRoom.roomType = [[self.fetchedResultsController fetchedObjects] objectAtIndex:row];

}

データベースコンテンツがローカライズされているNSLocalzedStringに注意してください。これはNSLogsの出力です。

2013-01-23 14:38:38.179 Wohnungsprotokoll[1311:c07] attic - Dachboden
2013-01-23 14:38:38.184 Wohnungsprotokoll[1311:c07] balcony - Balkon
2013-01-23 14:38:38.187 Wohnungsprotokoll[1311:c07] bath room - Badezimmer
2013-01-23 14:38:39.659 Wohnungsprotokoll[1311:c07] bed room - Schlafzimmer
2013-01-23 14:38:39.831 Wohnungsprotokoll[1311:c07] cellar - Keller
2013-01-23 14:38:40.789 Wohnungsprotokoll[1311:c07] children room - Kinderzimmer
2013-01-23 14:38:41.043 Wohnungsprotokoll[1311:c07] closet - Kammer
[...]

ご覧のとおり、英語の元のデータは適切に並べ替えられていますが、ドイツ語の翻訳(「-」に続く)は正しく並べ替えられていません。

これまでのところ明らかです。しかし、どうすればこれを回避できますか?

データベースコンテンツのローカライズされた値でこれを並べ替えるスマートな方法はありますか?つまり、データを配列にコピーし、後でその配列を並べ替えるのとは別の方法です。

4

1 に答える 1

1

Core Dataフェッチリクエスト(SQLiteベースのストアの場合)は永続属性でのみ並べ替えることができ、Objective-Cベースの並べ替え記述子も使用できません。したがって、(私が知る限り)フェッチされた結果コントローラーが。などの関数に従ってソートされたオブジェクトを返すようにする方法はありませんNSLocalizedString。(唯一の方法は、変換された文字列を追加の属性としてCore Dataエンティティに保存することです。)

ただし、データが完全に静的である場合(あなたが言ったように)、フェッチされた結果コントローラーは実際には必要ありません。を使用してオブジェクトをフェッチexecuteFetchRequestし、必要に応じて結果の配列を並べ替えることができます。

NSArray *unsortedRooms = [self.managedObjectContext executeFetchRequest:fetchRequest error:NULL];
NSArray *sortedRooms = [unsortedRooms sortedArrayUsingComparator:
           ^NSComparisonResult(RoomType *rt1, RoomType *rt2) {
               NSString *name1 = NSLocalizedString(rt1.typeName, @"Room-Type");
               NSString *name2 = NSLocalizedString(rt2.typeName, @"Room-Type");
               return [name1 compare:name2];
           }
];

(フェッチされた結果コントローラーの利点は、関連付けられた管理対象オブジェクトコンテキスト内のオブジェクトへの変更を監視し、結果セットの変更をそのデリゲート(通常はテーブルビュー)に報告することです。ただし、この場合、オブジェクトは変更されません。)

于 2013-01-23T14:21:09.627 に答える