Michael Loistl
Michael Loistl

Reputation: 271

Core Data - Sort descriptor for parent / child hierarchy

I get a JSON object from a HTML request which contains a hierarchical structure.

Sample from JSON object:

{
    "_id": "4f870f064f95ae0da8000002",
    "name": "Category",
    "parent_id": null
},
{
    "_id": "4f870f0e4f95ae0da8000004",
    "name": "Brand",
    "parent_id": null
},
{
    "_id": "4f8715bd4f95ae0da8000028",
    "name": "Dermalogica",
    "parent_id": "4f870f0e4f95ae0da8000004"
},
{
    "_id": "4f8715de4f95ae0da800002a",
    "name": "Molton Brown",
    "parent_id": "4f870f0e4f95ae0da8000004"
},
{
    "_id": "4f8715ea4f95ae0da800002c",
    "name": "Waxing",
    "parent_id": "4f870f064f95ae0da8000002"
},
{
    "_id": "4f8715f34f95ae0da800002e",
    "name": "Mens Hair",
    "parent_id": "4f870f064f95ae0da8000002"
},
{
    "_id": "4f8715fd4f95ae0da8000030",
    "name": "Ladies Hair",
    "parent_id": "4f870f064f95ae0da8000002"
},
{
    "_id": "4f87161f4f95ae0da8000032",
    "name": "Massage",
    "parent_id": "4f870f064f95ae0da8000002"
}

When I save it in the same way in just one entity, how would I define the fetch request (sorting) so that the objects are sorted with their parent / child relation ?

Upvotes: 0

Views: 1129

Answers (2)

kas-kad
kas-kad

Reputation: 3764

There is no way to sort this kind of data using sortDescriptors. This is how I solve the problem, having comments of article with threaded style discussions. After I download all comments, I need to reindexComments

-(void)reindexComments{
    NSArray *articleComments = self.comments.allObjects;
    [self fetchChildsWithComments:articleComments forParentId:0 num:1];
}

-(NSUInteger)fetchChildsWithComments:(NSArray*)articleComments forParentId:(NSUInteger)parentId num:(NSUInteger)num{
    NSArray *childComments = [articleComments filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"parentId == %u", parentId]];
    childComments = [childComments sortedArrayUsingComparator:^NSComparisonResult(Comment *c1, Comment *c2) {
        if (c1.commentIdValue < c2.commentIdValue){
            return NSOrderedAscending;
        }else{
            return NSOrderedDescending;
        }
    }];

    for (Comment *newRootComment in childComments){
        newRootComment.numValue = num;
        num++;
        num = [self fetchChildsWithComments:articleComments forParentId:newRootComment.commentIdValue num:num];
    }
    return num;
}

and finally I just sort by numValue field to get my nice threaded discussion

Upvotes: 0

Nikita Pestrov
Nikita Pestrov

Reputation: 5966

One Way - to use NSOrderedSet - http://developer.apple.com/library/mac/#documentation/Foundation/Reference/NSOrderedSet_Class/Reference/Reference.html

Second,more convinient(since NSOrderedSet is introduced in iOS 5),just a soimple NSFetchRequest with sortDescriptors.Since it is an Array, you can use a many descritors at a time as you want. So, using descriptors by parent_id and id should give you desired result.

NSFetchRequest *request = [[NSFetchRequest alloc]init];
    request.entity = [NSEntityDescription entityForName:@"Child" inManagedObjectContext:context];
   // request.predicate = [NSPredicate predicateWithFormat:@"parent_id =  %@",parent_ID];You don't need any predicate,right?
    request.sortDescriptors = [NSArray arrayWithObjects:[NSSortDescriptor sortDescriptorWithKey:@"parent_id" ascending:YES],[NSSortDescriptor sortDescriptorWithKey:@"_id" ascending:YES],nil];

return [context executeFetchRequest:request error:&error];

And,in Objective-C it's not convinient to use underlines in names. Hope, that helps.

Upvotes: -1

Related Questions