22

この質問をするのは私が初めてではないことはわかっていますが、本当に困惑しています..

基本的に、2 つのボタンがある画面があります。各ボタンは、日付に基づいて下のテーブルビューにデータをロードします。最初のテーブルビューの最初のロード (デフォルトでは左ボタンが選択されています) では、すべて正常に表示されます。右のボタンをクリックすると、空のテーブルビューが表示され、エラーが発生します

インデックス x でフェッチされたオブジェクトには、順不同のセクション名 'xxxxxx. オブジェクトはセクション名でソートする必要があります。

左のテーブル ビューに戻ると、データが表示されていません。両方のテーブルビューが空です。

各テーブルビューには、アイテムの開始時間に応じて 2 つのセクションがあります。セクションを削除すると、データは正常に表示されます。残念ながら、私はそれらが必要です..データは次のように2つのセクションに分類されます:

@interface NSString(agendaSessionKeyPath)
@property (nonatomic, readonly) NSString *sessionSection;
@end

@implementation NSString(agendaSessionKeyPath)

- (NSString *)sessionSection
{
    int timeValue = [[self stringByReplacingOccurrencesOfString:@":" withString:@""] intValue]; //turns 11:00 to 1100
    if (timeValue < 1200)
        return @"Morning";
     else
        return @"Afternoon";
}

取得リクエスト

- (void)viewDidLoad
{
     //other viewDidLoad stuff
    [self fetchSessions];
}

日付に基づいて左右のボタンからデータを並べ替えるメソッド:

- (void)fetchSessions
{
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
    [dateFormatter setDateFormat:@"yyyy-MM-dd"];

    NSDate* date = nil;
    if (selected == 0) //left button is selected
    {
        date = [dateFormatter dateFromString:@"2012-09-26"];
    }
    else if (selected == 1) //right button is selected
    {
        date = [dateFormatter dateFromString:@"2012-09-27"];
    }

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"date == %@", date];
    [self.fetchedResultsController.fetchRequest setPredicate:predicate];

    NSError *error;
    if (![[self fetchedResultsController] performFetch:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    }
}

フェッチされた結果のコントローラー

- (NSFetchedResultsController *)fetchedResultsController {
    self.managedObjectContext = [[MATCDatabaseController sharedDatabaseController] managedObjectContext];
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Session"];

    NSSortDescriptor *sort = [[NSSortDescriptor alloc]
                              initWithKey:@"title" ascending:YES];
    NSSortDescriptor *timeSort = [NSSortDescriptor sortDescriptorWithKey:@"timeValue" ascending:YES];
    [fetchRequest setSortDescriptors:@[timeSort, sort]];
    [fetchRequest setFetchBatchSize:20];

    NSFetchedResultsController *theFetchedResultsController =
    [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                        managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"startTime.sessionSection"
                                                   cacheName:nil];

    self.fetchedResultsController = theFetchedResultsController;
    [self.fetchedResultsController setDelegate:self];

    return _fetchedResultsController;

}

どんな助けでも大歓迎です!

4

2 に答える 2

26

わかりました、ちょっとのぞき見しました。

FRC を次のように初期化します。

[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                    managedObjectContext:self.managedObjectContext
                                      sectionNameKeyPath:@"startTime.sessionSection"
                                               cacheName:nil];

これは、セクション タイトルがキー パス経由で取得されることを示していますstartTime.sessionSection

これで、FRC に渡されたフェッチ要求の最初のソート記述子が、セクションのソートに使用されます。あなたが最初に提供しているソート記述子は、timeValue正しくないようです。

最初のソート記述子は、セクション タイトルのソートを指定する必要があります。それを変更すると、準備が整います。

編集

情報をありがとう。私はまだ少し迷っています。sectionNameKeyPath に割り当てる前に、startTime.sessionSection にソート記述子を追加する必要があるということですか? 試してみましたが、まだ運がありません。timeValue と startTime.sessionSection は関連しています。それはそれでしょうか?– ハト工場

最初のソート記述子がセクションに基づいてデータを適切にソートすることを確認する必要があります。あなたの場合、時間は言葉に変換されています。最初の並べ替え記述子は時間用であり、データが時間に基づいて並べ替えられると、セクションが正しく並べ替えられず、エラーが発生します。

最初のソート記述子は、セクション データを満たす必要があります。だから、最初に、私は試してみます...

[fetchRequest setSortDescriptors:@[
    [NSSortDescriptor sortDescriptorWithKey:@"startTime.sessionSection"
                                  ascending:NO],
    [NSSortDescriptor sortDescriptorWithKey:@"timeValue"
                                  ascending:YES],
    [NSSortDescriptor sortDescriptorWithKey:@"title"
                                  ascending:YES] ];

大量のデータがある場合、セクション メカニズムが遅くなることに注意してください。その場合は、このセクション データをデータベースに追加することをお勧めします。

于 2012-08-27T23:39:20.573 に答える
0

私も同様の問題を抱えています。おそらく誰かが役に立つと思います。

DB から金融取引を取得し、月ごとに区分しました。

DB にはプロパティ trDate があります。これはトランザクションの日付です。ただし、trMonth は次のような一時的なプロパティです。

- (NSString*)trMonth {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"LLLL"];
[dateFormatter setLocale:[NSLocale currentLocale]];

return [dateFormatter stringFromDate:trDate];
}

次のように FetchResultsController で使用されました。

...
NSSortDescriptor *sortDate = [[NSSortDescriptor alloc] initWithKey:@"trDate" ascending:YES];

[fetchRequest setSortDescriptors:@[sortDate]];

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"trMonth" cacheName:nil];
...

これは本番環境ではうまく機能しましたが、アプリがクラッシュし始めた後、根本的な問題を発見した後、(たとえば) 7 月に 2 つのトランザクションがあることがわかりました: 2014 年 7 月と 2015 年 7 月です。 2014 < 2015 7月ですが、私の方法ではそれらを同じ月と見なしました。ソリューションは、月名だけでなく年もセクション名として使用されました。

- (NSString*)trMonthYear {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"LLLL yyyy"]; // added year also
[dateFormatter setLocale:[NSLocale currentLocale]];

return [dateFormatter stringFromDate:trDate];
}
于 2015-09-15T07:44:25.673 に答える