1

i have list of brands stored in Core Data, each brand is associated with multiple contents. The contents have a flag called downStatus which is used to denote whether a content is downloaded or not. The following method is used to fetch all the brands from Core data sorted with brand name

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

}

Now i want to sort using the downStatus which is in the Content. So it will be like, downloaded brands in Alphabetical Order and then Un-Downloaded brands in Alphabetical order. The downStatus takes two values 1 for downloaded 0 for not downloaded. Please help.

2 Answers 2

1

One way to do it is by making 2 fetchRequests to CoreData using the NSPredicate with value 1/0 on downStatus property and using the same alphabetical sortDescriptor.

Now create a new Array by adding the 0 array to the 1 array. In your code it would look something like this:

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

-- edit, adding answer for NSDictionary with downStatus key

-(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);
}
Sign up to request clarification or add additional context in comments.

5 Comments

hi, thanks for the reply. Now it gives me this error *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'keypath downStatus not found in entity <NSSQLEntity Brand id=1>' .... its because downStatus is in Content not Brand
You don't have a downStatus property in your Core Data object? What kind of data is it you are retrieving from Core Data. I'm guessing a dictionary, if so then you would need an other approach.
Its actually Content is associated with Brand and each content have downStatus property as 1 or 0. I need to fetch all the Brands whose content downStatus is 1 or 0 and sorted by brandName. I may have to mention some relationships here, but dont know how to do it.
Brand and Content are 2 separate entities
Hi, @Michael.... your solution worked. There was another attribute in Brand using which we can come to know if it is downloaded or not. Thanks alot.
0

If you plan to use the fetch result in a UITableViewController, you could use the sectionNameKeyPath of your fetchedResultsController for the downStatus and keep your sort descriptor for the brand name. Can look like this:

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

Place this in the header file of your NSManagedObject :

-(NSString*)customSectionTitle;

And this in .m :

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

If you do not plan to use a fetchedResultsController, just sort first by downStatus and then by brand name.

2 Comments

no, m not using any tableLayout, m creating a GridLayout with this data.
This I believe is covered with the last sentence of my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.