使用transient属性排序UITableView节 [英] Order UITableView sections using a transient attribute

查看:154
本文介绍了使用transient属性排序UITableView节的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我之前已发布过类似的问题,请查看此链接 UITableView节未按预期排序
我需要解决的问题如下:
我有一个带有自定义节的tableView。段标题取自在名为ToDoItem的NSManagegObject子类定义的瞬态属性。 transient属性称为sectionIdentifier。在我的tableView viewController我有一个fetchedResultsController与两个NSSortDescriptors命令对象:

I have published a similar question before, please take a look at this link UITableView sections are not ordered as expected The problem I need to resolve is following: I have a tableView with customised sections. The section titles are taken from a transient attribute defined at a NSManagegObject subclass called ToDoItem. The transient attribute is called sectionIdentifier. In my tableView viewController I have a fetchedResultsController with two NSSortDescriptors to order the objects:

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

考虑到瞬态属性不能用作NSSortDescriptor处的initWithKey值,现在根据todoDueDate的属性值而不是由sectionIdentifier值排序,这应该是我的预期顺序。
我把下面的代码形式两个classer,第一个定义sectionIdentifier我的ToDoItem类和第二个tableView vieController类。

Taking into account that a transient attribute can't be used as initWithKey value at a NSSortDescriptor, the sections are ordered now depending on the attribute value for todoDueDate and not by the sectionIdentifier value, which should be my expected order. I put below the code form both classer, first definition of sectionIdentifier i the ToDoItem class and second the tableView vieController class.

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

}

这是我想获取的节序:

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

ToDoItemsTableViewController.m

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 是unspecified的条目。
问题是第一个排序描述符todoDueDate必须与
节标识符兼容。因此,对于节,您不能使用两个单独的属性 todoDueDate
isSomeDay

I assume that the "SOMEDAY" entries are those where the todoDueDate is "unspecified". The problem is that the first sort descriptor "todoDueDate" must be compatible with the section identifier. So you cannot use two separate properties todoDueDate and isSomeDay for the sections.

因此,不应使用单独的属性 isSomeDay ,您应该分配这些对象
a在未来很远的值: / p>

Therefore, instead of using a separate property isSomeDay, you should assign those objects a value that is far in the future:

self.todoDueDate = [NSDate distantFuture];

,以便在所有其他对象后自动排序。
然后你可以在 sectionIdentifier 方法中这样做:

so that they are automatically ordered after all other objects. Then you can do something like this in the sectionIdentifier method:

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

viewForHeaderInSection 中,你不应该检查节号,
而不是节名称(0 ,1,...)。原因是一个段可能为空:
如果没有OVERDUE对象,则TODAY是段#0。

Also in viewForHeaderInSection, you should not check for the section number, but for the section name ("0", "1", ...). The reason is that a section may be empty: If there are not "OVERDUE" objects, then "TODAY" is section #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 ...
}

这篇关于使用transient属性排序UITableView节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆