2

のセクションを定義するために、このカスタム生成された配列UITableViewがありますが、ご覧のとおり、すべての項目が Core Data を介して取得され、個別に並べ替えられます。

これは私のカスタムコードです:

-(NSArray *)tasks {
    NSManagedObjectContext *managedObjectContext = [self.fetchedResultsController managedObjectContext];

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Task" inManagedObjectContext:managedObjectContext];
    [request setEntity:entity];

    // retrive the objects with a given value for a certain property
    [request setPredicate:nil];

    // Edit the sort key as appropriate.
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"scheduledDate" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    [request setSortDescriptors:sortDescriptors];

    // 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:request managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:@"Root"];
    aFetchedResultsController.delegate = self;

    NSError *error = nil;
    NSArray *result = [managedObjectContext executeFetchRequest:request error:&error];

    if ((result != nil) && ([result count]) && (error == nil)){
         return [NSMutableArray arrayWithArray:result];
    }
    return [NSMutableArray array];
}

-(NSMutableArray *)sectionsArray {
    // Fetch the scheduledDate check if it is in any of the term arrays and dump it in that section.
    NSArray *tasks = [self tasks]; 
    if (tasks) {
        NSArray *scheduledTasks = [tasks valueForKey:@"scheduledDate"];
        scheduledTasks = [[[NSSet setWithArray:scheduledTasks] allObjects] sortedArrayUsingSelector:@selector(compare:)];

        NSMutableArray *shortTermTasks = [NSMutableArray array];
        NSMutableArray *midTermTasks = [NSMutableArray array];
        NSMutableArray *longTermTasks = [NSMutableArray array];

        for (NSDate *scheduledDate in scheduledTasks) {
            NSString *dateString = [NSString dateStringFromFullDate:scheduledDate];

            NSPredicate *pred = [NSPredicate predicateWithFormat:@"scheduledDate == %@", scheduledDate];
            NSManagedObject *task = [[tasks filteredArrayUsingPredicate:pred] lastObject]; 

            if ([[self shortTermDateStrings] containsObject:dateString]) {
                [shortTermTasks addObject:task];
            }
            if ([[self midTermDateStrings] containsObject:dateString]) {
                [midTermTasks addObject:task];
            }
            if ([[self longTermDateStrings] containsObject:dateString]) {
                [longTermTasks addObject:task];
            }
        }
        sectionsArray = [NSMutableArray arrayWithObjects:shortTermTasks,midTermTasks,longTermTasks, nil];
        return sectionsArray;
    }
    return [NSMutableArray array];
}

(NSFetchedResultsController *)fetchedResultsControllerセクションの編成方法を定義することを調査したところ、ここでカスタム配列を生成する方法が問題になりました。

(NSFetchedResultsController *)fetchedResultsControllerはこのように見えます:

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

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Task" 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 = [[NSSortDescriptor alloc] initWithKey:@"scheduledDate" ascending:YES];
    NSArray *sortDescriptors = @[sortDescriptor];

    [fetchRequest setSortDescriptors:sortDescriptors];

    // 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:@"Master"];

    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;
}    

更新: を生成するためのコードshortTermmidTermおよびlongTerm日付に従って[NSDate date]sectionIdentifier 注: 私はこれのために多くのカテゴリ作成しました。NSDateNSString

-(NSArray *)shortTermDates {
    NSArray *fullDateList = [NSDate daysFrom:[NSDate date] to:[NSDate dateWithDaysFromNow:2]];
    NSMutableArray *daysList = [NSMutableArray array];

    NSString *dateString = nil;
    for (NSDate *date in fullDateList) {
        dateString = [NSString dateStringFromFullDate:date];
        [daysList addObject:dateString];
    }
    return fullDateList;
}

-(NSArray *)shortTermDateStrings {
    NSMutableArray *daysList = [NSMutableArray array];

    NSString *dateString = nil;
    for (NSDate *date in [self shortTermDates]) {
        dateString = [NSString dateStringFromFullDate:date];
        [daysList addObject:dateString];
    }
    return daysList;
}

-(NSArray *)midTermDates {
    NSDate *startDate = [[self shortTermDates] lastObject];
    int addition = 5;
    int dayFromLastTermDate = [NSDate extractDayFromDate:[[self shortTermDates] lastObject]];
    NSDate *date = [NSDate dateWithYear:[NSDate extractYearFromDate:startDate] month:[NSDate extractMonthFromDate:startDate] day:dayFromLastTermDate+addition hour:[NSDate extractHourFromDate:startDate] minute:[NSDate extractMinuteFromDate:startDate] second:[NSDate extractSecondFromDate:startDate]];
    NSArray *fullDateList = [NSDate daysFrom:startDate to:date];
    return fullDateList;
}

-(NSArray *)midTermDateStrings {
    NSMutableArray *daysList = [NSMutableArray array];

    NSString *dateString = nil;
    for (NSDate *date in [self midTermDates]) {
        dateString = [NSString dateStringFromFullDate:date];
        [daysList addObject:dateString];
    }
    return daysList;
}

-(NSArray *)longTermDates {
    NSDate *startDate = [[self midTermDates] lastObject];
    int addition = 8;
    int dayFromLastTermDate = [NSDate extractDayFromDate:[[self midTermDates] lastObject]];
    NSDate *date = [NSDate dateWithYear:[NSDate extractYearFromDate:startDate] month:[NSDate extractMonthFromDate:startDate] day:dayFromLastTermDate+addition hour:[NSDate extractHourFromDate:startDate] minute:[NSDate extractMinuteFromDate:startDate] second:[NSDate extractSecondFromDate:startDate]];
    NSArray *fullDateList = [NSDate daysFrom:startDate to:date];
    return fullDateList;
}

-(NSArray *)longTermDateStrings {
    NSMutableArray *daysList = [NSMutableArray array];

    NSString *dateString = nil;
    for (NSDate *date in [self longTermDates]) {
        dateString = [NSString dateStringFromFullDate:date];
        [daysList addObject:dateString];
    }
    return daysList;
}

- (NSString *)sectionIdentifier;
{
    NSDate *date = self.scheduledDate;
    if ([date compare:[[self shortTermDates] lastObject]] == NSOrderedAscending) {
        return @"0";
        if ([date compare:[[self midTermDates] lastObject]] == NSOrderedAscending) {
            return @"1";
        } else {
            return @"2";
        }
    }
    return nil;
}
4

2 に答える 2

3

フェッチされた結果コントローラー (FRC) を使用してテーブル ビューをセクションにグループ化するには、次の 2 つのことが必要です。

  • sectionNameKeyPath:FRCを設定する必要があります。これは、エンティティの任意の属性 (永続的または一時的) にすることも、管理対象オブジェクト サブクラスの任意のインスタンス メソッドにすることもできます。
  • sectionNameKeyPath:FRC 要求の最初の並べ替え記述子は、プロパティ/メソッドと同じ相対順序でオブジェクトを並べ替える必要があります。このソート記述子は、エンティティの永続属性のみを使用できます。

オブジェクトは属性に従ってすでにソートされていscheduledDateます。オブジェクトをセクションにグループ化するには、管理対象オブジェクトのサブクラスに「適切な」インスタンス メソッドを追加するだけです。

いくつかの日付変数shortTermLimitmidTermLimit. 次に、管理対象オブジェクト サブクラスのクラス カテゴリで次のメソッドを定義できます。

@implementation Task (CategoryMethods)

- (NSString *)sectionIdentifier;
{
    NSDate *date = self.scheduledDate;
    if ([date compare:shortTermLimit] == NSOrderedAscending) {
        return @"0";
    } else if ([date compare:midTermLimit] == NSOrderedAscending) {
        return @"1";
    } else {
        return @"2";
    }
}

@end

次に、引数を使用して FRC を作成します。

sectionNameKeyPath:@"sectionIdentifier"

以前にスケジュールされたすべてのタスクはshortTermLimitセクション「0」にグループ化され、以前にスケジュールされたタスクはmidTermLimitセクション「1」にグループ化され、残りのタスクはセクション「2」にグループ化されます。

相対的な順序付け (「0」、「1」、「2」) は、 を使用したソート記述子と互換性があることに注意してくださいscheduledDate

ただし、セクション ヘッダーとして "0"、"1"、"2" は必要ないため、titleForHeaderInSectionデリゲート メソッドを変更する必要があります。

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
    NSString *name = [sectionInfo name];
    if ([name isEqualToString:@"0"]) {
        return @"Short Term";
    } else if ([name isEqualToString:@"1"]) {
        return @"Mid Term";
    } else {
        return @"Long Term";
    }
}

また、Apple Developer Library の「DateSectionTitles」サンプル プロジェクトも参照してください。これは、年と月ごとにオブジェクトをセクションにグループ化するのと同様に機能します。

于 2013-07-20T18:09:23.590 に答える
0

Task一時属性をエンティティに追加し、 のように呼び出しますsectionName。エンティティが保存されたとき、またはscheduledDateが設定されたときに、新しい を計算してsectionName保存します。sectionNameFRC が使用するキー パスとして設定します。

于 2013-07-20T17:14:13.197 に答える