ios - 使用 transient 属性对 UITableView 部分进行排序

标签 ios core-data uitableview

我之前发过类似的问题,请看这个链接UITableView sections are not ordered as expected 我需要解决的问题如下: 我有一个带有自定义部分的 tableView。部分标题取自在名为 ToDoItem 的 NSManagegObject 子类中定义的临时属性。 transient 属性称为 sectionIdentifier。在我的 tableView viewController 中,我有一个带有两个 NSSortDescriptor 的 fetchedResultsController 来排序对象:

  NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey:@"todoDueDate" ascending:YES];
    NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc]initWithKey:@"todoName" ascending:YES];

考虑到 transient 属性不能用作 NSSortDescriptor 的 initWithKey 值,现在根据 todoDueDate 的属性值而不是 sectionIdentifier 值对部分进行排序,这应该是我预期的顺序。 我将两个分类器的代码放在代码下方,第一个是 ToDoItem 类的 sectionIdentifier 定义,第二个是 tableView vieController 类。

-(NSString *)sectionIdentifier{

    [self willAccessValueForKey:@"sectionIdentifier"];
    NSString *tmp = [self primitiveValueForKey:@"sectionIdentifier"];
    [self didAccessValueForKey:@"sectionIdentifier"];


    if ([self.isSomeDay isEqualToString:@"noissomeday"]){//SI NO ES SOMEDAY

    if (!tmp){



        //NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

        NSCalendar *calendar = [NSCalendar currentCalendar];
        NSInteger comps = (NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit);

        NSDate *today = [NSDate date];
        NSDate *date = self.todoDueDate;


        NSDateComponents *date1Components = [calendar components:comps
                                                        fromDate: today];
        NSDateComponents *date2Components = [calendar components:comps
                                                        fromDate: date];
        today = [calendar dateFromComponents:date1Components];
        date = [calendar dateFromComponents:date2Components];




        NSInteger daysAfterToday = [calendar components:NSDayCalendarUnit
                                               fromDate:today toDate:date options:0].day;
       // NSString *section;
        if (daysAfterToday < 0) {
            tmp  = @"0";
        } else if (daysAfterToday == 0) {
            tmp = @"1";
        } else if (daysAfterToday > 0 && daysAfterToday < 2) {
            tmp = @"2";
        } else {
            tmp = @"3";
        }


        NSLog(@"TODAY = %@", today);
        NSLog(@"DATE = %@", date);
        NSLog(@"DAYS AFTER TODAY = %ld",(long)daysAfterToday);



        [self setPrimitiveValue:tmp forKey:@"sectionIdentifier"];

    }
    }
    //no is someday
    else if ([self.isSomeDay isEqualToString:@"issomeday"]){
        tmp = @"4";
    }
    NSLog(@"Tmp= %@",tmp);
    return tmp;

}

也就是我要获取的section order:

1. OVERDUE, sectionIdentifier = 0
2. TODAY, sectionIdentifier = 1
3. TOMORROW, sectionIdentifier = 2
4. UPCOMING, sectionIdentifier = 3
5. SOMEDAY, sectionIdentifier = 4

ToDoItemsTableViewController.m

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    if (tableView == self.searchDisplayController.searchResultsTableView)
    {
        return 1;
    }
    else
    {
        return [[self.fetchedResultsController sections]count];
    }
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (tableView == self.searchDisplayController.searchResultsTableView)
    {
        return [self.searchResults count];
    }
    else {
    id<NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections]objectAtIndex:section];
    return [sectionInfo numberOfObjects];

    }
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
   UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    // Configure the cell...

    ToDoItem *toDoItem = nil;



    if (tableView == self.searchDisplayController.searchResultsTableView)
    {
        if (cell==nil) {
            cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
            cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator;

        }
        NSLog(@"Configuring cell to show search results");
        toDoItem = [self.searchResults objectAtIndex:indexPath.row];
        cell.textLabel.text = toDoItem.todoName;



        NSDate *fechaToDO = toDoItem.todoDueDate;

        NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
        [dateFormatter setDateFormat:@"EEEE, dd MMMM YYYY"];
        NSString *fechaToDo = [dateFormatter stringFromDate:fechaToDO];

        NSString *valorSomeDay = toDoItem.isSomeDay;
        if ([valorSomeDay isEqualToString:@"issomeday"]){
            cell.detailTextLabel.text = @"Someday";
        }
        else {

        cell.detailTextLabel.text = fechaToDo;
        }
    }
    else
    {


    ToDoItem *todoitem = [self.fetchedResultsController objectAtIndexPath:indexPath];
    cell.textLabel.text = todoitem.todoName;



    NSDate *fechaToDO = todoitem.todoDueDate;

    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
    [dateFormatter setDateFormat:@"EEEE, dd MMMM YYYY"];
    NSString *fechaToDo = [dateFormatter stringFromDate:fechaToDO];



        NSString *valorSomeDay = todoitem.isSomeDay;
        if ([valorSomeDay isEqualToString:@"issomeday"]){
            cell.detailTextLabel.text = @"Someday";
        }
        else {

            cell.detailTextLabel.text = fechaToDo;
        }
    }
    return cell;
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    static NSString *header = @"customHeader";

    UITableViewHeaderFooterView *vHeader;

    vHeader = [tableView dequeueReusableHeaderFooterViewWithIdentifier:header];

    if (!vHeader) {
        vHeader = [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:header];
        vHeader.textLabel.backgroundColor = [UIColor redColor];
        vHeader.textLabel.textColor = [UIColor whiteColor];

        vHeader.contentView.backgroundColor = [UIColor redColor];
    }

    if (section == 0) {
        vHeader.textLabel.backgroundColor = [UIColor redColor];
        vHeader.textLabel.textColor = [UIColor whiteColor];


        vHeader.contentView.backgroundColor = [UIColor redColor];
    }

    else if (section == 1) {
        vHeader.textLabel.backgroundColor = [UIColor orangeColor];
        vHeader.textLabel.textColor = [UIColor blueColor];

        vHeader.contentView.backgroundColor = [UIColor orangeColor];
    }
    else if (section == 2) {
        vHeader.textLabel.backgroundColor = [UIColor greenColor];
        vHeader.textLabel.textColor = [UIColor whiteColor];

        vHeader.contentView.backgroundColor = [UIColor greenColor];
    }
    else if (section == 3) {
        vHeader.textLabel.backgroundColor = [UIColor greenColor];
        vHeader.textLabel.textColor = [UIColor whiteColor];

        vHeader.contentView.backgroundColor = [UIColor greenColor];
    }
    else if (section == 4) {
        vHeader.textLabel.backgroundColor = [UIColor blueColor];
        vHeader.textLabel.textColor = [UIColor whiteColor];

        vHeader.contentView.backgroundColor = [UIColor blueColor];
    }


    vHeader.textLabel.text = [self tableView:tableView titleForHeaderInSection:section];

    return vHeader;
}
-(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{

    if (tableView == self.searchDisplayController.searchResultsTableView){
        NSString *valor = [NSString stringWithFormat:@"S E A R C H   R E S U L T S (%d)",[self.searchResults count]];
        return valor;
    }
    else {


    id <NSFetchedResultsSectionInfo> theSection = [[self.fetchedResultsController sections]objectAtIndex:section];
    NSString *sectionname = [theSection name];

    if ([sectionname isEqualToString:@"0"]){

        NSString *valor = [NSString stringWithFormat:@"O V E R D U E   (%d)", [self.tableView
                                                             numberOfRowsInSection:section]];
        return valor;
    }
    else if ([sectionname isEqualToString:@"1"]){

        NSString *valor = [NSString stringWithFormat:@"T O D A Y   (%d)", [self.tableView
                                           numberOfRowsInSection:section]];
        return valor;
    }
    else if ([sectionname isEqualToString:@"2"]){

        NSString *valor = [NSString stringWithFormat:@"T O M O R R O W   (%d)", [self.tableView
                                                             numberOfRowsInSection:section]];
        return valor;
    }
    else if ([sectionname isEqualToString:@"3"]){

        NSString *valor = [NSString stringWithFormat:@"U P C O M I N G   (%d)", [self.tableView
                                                                                 numberOfRowsInSection:section]];
        return valor;
    }

    else if ([sectionname isEqualToString:@"4"]){

        NSString *valor = [NSString stringWithFormat:@"S O M E D A Y    (%d)", [self.tableView
                                                                                 numberOfRowsInSection:section]];
        return valor;
    }


    if ([[self.fetchedResultsController sections]count]>0){
        id<NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections]objectAtIndex:section];
        return [sectionInfo name];
    }
    else{
        return nil;
    }
    }

}


#pragma mark - Fetched Results Controller Section

-(NSFetchedResultsController*)fetchedResultsController{

    if (_fetchedResultsController != nil){
        return _fetchedResultsController;
    }
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];
    NSManagedObjectContext *context = self.managedObjectContext;
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"ToDoItem" inManagedObjectContext:context];
    [fetchRequest setEntity:entity];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey:@"todoDueDate" ascending:YES];
    NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc]initWithKey:@"todoName" ascending:YES];

    NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:sortDescriptor,sortDescriptor1, nil];
    fetchRequest.sortDescriptors = sortDescriptors;
    _fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:@"sectionIdentifier" cacheName:nil];
    _fetchedResultsController.delegate = self;
    return _fetchedResultsController;
}

最佳答案

我假设“SOMEDAY”条目是那些 todoDueDate 是“未指定”的条目。 问题是第一个排序描述符“todoDueDate”必须兼容 节标识符。所以你不能使用两个单独的属性 todoDueDateisSomeDay 部分。

因此,不要使用单独的属性 isSomeDay,您应该分配这些对象 一个遥远 future 的值:

self.todoDueDate = [NSDate distantFuture];

以便它们自动排在所有其他对象之后。 然后你可以在 sectionIdentifier 方法中做这样的事情:

if ([self.todoDueDate isEqualToDate:[NSDate distantFuture]) {
    tmp = @"4";
} else {
    // ... your other checks for overdue, today, tomorrow, upcoming
}

同样在 viewForHeaderInSection 中,您不应该检查节号, 但对于部分名称(“0”、“1”、...)。原因是一个部分可能是空的: 如果没有“OVERDUE”对象,则“TODAY”是第 0 部分。

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    id <NSFetchedResultsSectionInfo> theSection = [[self.fetchedResultsController sections] objectAtIndex:section];

    NSString *tmp = [theSection name];
    if ([tmp isEqualToString:@"0"]) {
        // OVERDUE
    } else if ([tmp isEqualToString:@"1"]) {
        // TODAY
    } else 
    // and so on ...
}

关于ios - 使用 transient 属性对 UITableView 部分进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21222361/

相关文章:

ios - 如何防止两个tableview单元格动画同时发生

ios - UITableView 中的 UITextField 与 DatePicker 的 InputView

android - 没有Phonegap构建的Android Phonegap应用

ios - 核心数据 : Query to one-to-many-to-many relationship

iphone - 选项卡推送通知 cocos2d 游戏崩溃

objective-c - 在不同的托管对象上下文中看不到 ios coredata 更新 - 上下文之间的数据不同

ios - 如何在核心数据中存储audioPlayer实例的引用?

ios - 你如何从 UIViewController 访问 scrollViewDidScroll

ios - 基于字符串数组 (Swift) 在 UITableView 中的 viewdidload 上选择单元格

ios - dequeueReusableCellWithIdentifier 快速加载需要时间