【问题标题】:Sorting in Core Data with Multiple Values对具有多个值的核心数据进行排序
【发布时间】:2014-07-08 07:06:03
【问题描述】:

我有存储在 Core Data 中的品牌列表,每个品牌都与多个内容相关联。内容有一个名为downStatus 的标志,用于表示是否下载了内容。以下方法用于从 Core 数据中获取按品牌名称排序的所有品牌

-(void)getDownloadedBrands{

AppDelegate *aAppDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;

NSMutableArray *aBrands = [[NSMutableArray alloc] init];


NSEntityDescription *entity =
[NSEntityDescription entityForName:@"Brand" inManagedObjectContext:aAppDelegate.managedobjectcontext];
 NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];

NSSortDescriptor *sort=[[NSSortDescriptor alloc]initWithKey:@"brandName" ascending:YES];
//NSSortDescriptor *sort1=[[NSSortDescriptor alloc]initWithKey:@"downStatus" ascending:YES];

[request setSortDescriptors:[NSArray arrayWithObjects:sort, nil]];

aBrands =(NSMutableArray *)[aAppDelegate.managedobjectcontext executeFetchRequest:request error:nil];
[request release];
[sort release];
NSLog(@"%@",aBrands);

brands = [[NSMutableArray alloc]initWithArray:aBrands];

aAppDelegate.dbBrandArr = brands;

[self loadGridView];

}

现在我想使用内容中的downStatus 进行排序。因此,就像按字母顺序下载的品牌,然后按字母顺序未下载的品牌。 downStatus 采用两个值 1 表示已下载 0 表示未下载。请帮忙。

【问题讨论】:

    标签: objective-c core-data nssortdescriptor


    【解决方案1】:

    一种方法是使用带有值1/0 on downStatus 属性的NSPredicate2 fetchRequests 转换为CoreData,并使用相同的字母顺序sortDescriptor

    现在通过将 0 数组添加到 1 数组来创建一个新数组。在您的代码中,它看起来像这样:

    -(void)getDownloadedBrands{
        AppDelegate *aAppDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    
        //2 arrays
        NSMutableArray *aBrands0 = [[NSMutableArray alloc] init];
        NSMutableArray *aBrands1 = [[NSMutableArray alloc] init];
        //set entity en make requests
        NSEntityDescription *entity = [NSEntityDescription entityForName:@"Brand" inManagedObjectContext:aAppDelegate.managedobjectcontext];
        NSFetchRequest *request0 = [[NSFetchRequest alloc] init];
        NSFetchRequest *request1 = [[NSFetchRequest alloc] init];
        [request0 setEntity:entity];
        [request1 setEntity:entity];
        //create sortDescriptor alphabetically
        NSSortDescriptor *sort=[[NSSortDescriptor alloc]initWithKey:@"brandName" ascending:YES];
        //create predicates on downStatus property
        NSPredicate *predicate0 = [NSPredicate predicateWithFormat:@"downStatus == %@", [NSNumber numberWithBool:0]];
        NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"downStatus == %@", [NSNumber numberWithBool:1]];
        //set predicates to the requests
        [request0 setPredicate:predicate0];
        [request1 setPredicate:predicate1];
        //set sortDescriptor to both requests
        [request0 setSortDescriptors:[NSArray arrayWithObjects:sort, nil]];
        [request1 setSortDescriptors:[NSArray arrayWithObjects:sort, nil]];
        //fetch arrays with downStatus 1/0
        aBrands0 =(NSMutableArray *)[aAppDelegate.managedobjectcontext executeFetchRequest:request0 error:nil];
        aBrands1 =(NSMutableArray *)[aAppDelegate.managedobjectcontext executeFetchRequest:request1 error:nil];
        //release requests // NOT USING ARC??
        [request0 release];
        [request1 release];
        [sort release];
        //log results
        NSLog(@"aBrands0: %@",aBrands0);
        NSLog(@"aBrands1: %@",aBrands1);
        //add object 0 array to 1 array
        NSArray *combinedArray = [aBrands1 arrayByAddingObjectsFromArray:aBrands0];
        //copy array to brands
        brands = [[NSMutableArray alloc]initWithArray:combinedArray];
        //set property on appDelegate
        aAppDelegate.dbBrandArr = brands;
        //reload tableView
        [self loadGridView];
    }
    

    -- 编辑,使用 downStatus 键为 NSDictionary 添加答案

    -(void)getDownloadedBrands{
        AppDelegate *aAppDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    
        NSMutableArray *aBrands = [[NSMutableArray alloc] init];
    
    
        NSEntityDescription *entity = [NSEntityDescription entityForName:@"Brand" inManagedObjectContext:aAppDelegate.managedobjectcontext];
        NSFetchRequest *request = [[NSFetchRequest alloc] init];
        [request setEntity:entity];
    
        NSSortDescriptor *sort=[[NSSortDescriptor alloc]initWithKey:@"brandName" ascending:YES];
        //NSSortDescriptor *sort1=[[NSSortDescriptor alloc]initWithKey:@"downStatus" ascending:YES];
    
        [request setSortDescriptors:[NSArray arrayWithObjects:sort, nil]];
    
        aBrands =(NSMutableArray *)[aAppDelegate.managedobjectcontext executeFetchRequest:request error:nil];
    
        NSMutableArray *aBrands0 = [[NSMutableArray alloc] init];
        NSMutableArray *aBrands1 = [[NSMutableArray alloc] init];
        for (NSDictionary *dict in aBrands) {
            if ([dict valueForKeyPath:@"downStatus"] == YES)
            {
                //add to 1 array
                [aBrands1 addObject:dict];
            }
            else
            {
                //add to 0 array
                [aBrands0 addObject:dict];
            }
        }
    
        //sort arrays
        NSArray * array1 = [aBrands1 sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];
        NSArray * array0 = [aBrands0 sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];
        NSArray * allArray = [aBrands1 arrayByAddingObjectsFromArray:aBrands0];
    
        //combine arrays
    
        //copy array to brands
        brands = [[NSMutableArray alloc]initWithArray:combinedArray];
        //set property on appDelegate
        aAppDelegate.dbBrandArr = brands;
        //reload tableView
        [self loadGridView];
    
        [request release];
        [sort release];
        NSLog(@"%@",aBrands);
    }
    

    【讨论】:

    • 嗨,感谢您的回复。现在它给了我这个错误*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'keypath downStatus not found in entity <NSSQLEntity Brand id=1>' .... 这是因为downStatus 在内容而不是品牌中
    • 您的核心数据对象中没有 downStatus 属性?您正在从 Core Data 检索什么样的数据。我猜是字典,如果是这样,那么你需要另一种方法。
    • 它实际上是ContentBrand 相关联,并且每个内容都有downStatus 属性为10。我需要获取内容 downStatus 为 1 或 0 并按品牌名称排序的所有品牌。这里可能不得不提一些关系,但是不知道怎么做。
    • BrandContent 是 2 个独立的实体
    • 嗨,@Michael....您的解决方案有效。 Brand 中还有另一个属性,我们可以使用它来知道它是否被下载。非常感谢。
    【解决方案2】:

    如果您打算在 UITableViewController 中使用获取结果,则可以将 fetchedResultsController 的 sectionNameKeyPath 用于 downStatus,并保留品牌名称的排序描述符。可以是这样的:

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

    把它放在你的 NSManagedObject 的头文件中:

    -(NSString*)customSectionTitle;
    

    这在 .m 中:

    -(NSString*)customSectionTitle{
        if ([downStatus boolValue] == YES) {
            return @"Downloaded";
        }
        else {return @"Not Downloaded";}
    }
    

    如果您不打算使用 fetchedResultsController,只需先按 downStatus 排序,然后按品牌名称。

    【讨论】:

    • 不,m 没有使用任何 tableLayout,m 用这些数据创建一个 GridLayout。
    • 我相信我的答案的最后一句话已经涵盖了这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多