Counting Items in Core Data

Discussion in 'iPhone/iPad Programming' started by sleaver, Aug 20, 2010.

  1. macrumors member

    Joined:
    Jul 21, 2010
    #1
    Hi

    In my RSS Reader App when the application quits or enters the background I count the unread items in the entity that holds the storys with the following:

    PHP:
    - (int)countUnreadItems {
        
    NSFetchRequest *request = [[NSFetchRequest allocinit];
        [
    request setEntity:[NSEntityDescription entityForName:@"FeedItem" inManagedObjectContext:managedObjectContext]];
        
        
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@" read = 0"];
        [
    request setPredicate:predicate];

        
        
    NSError *err;
        
    NSUInteger count = [managedObjectContext countForFetchRequest:request error:&err];
        if(
    count == NSNotFound) {
            
    //Handle error
        
    }
            
        return 
    count;
    That is in a class but is called from the app delegate so the passed managed object context is:


    PHP:
    - (NSManagedObjectContext *)managedObjectContext {
        
        if (
    managedObjectContext_ != nil) {
            return 
    managedObjectContext_;
        }
        
        
    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
        if (
    coordinator != nil) {
            
    managedObjectContext_ = [[NSManagedObjectContext allocinit];
            [
    managedObjectContext_ setPersistentStoreCoordinator:coordinator];
        }
        return 
    managedObjectContext_;
    That works fine, however I have a FeedInfo entity (holding the name, summary URL of the feed etc) and obviously with a relationship between the two. In the FeedInfo entity I have a 'show' attribute which lets the user decide if they wish for the feed to display in the app.

    So, say I have 5 feeds with 20 unread items each, the application badge shows 100 which is correct. However if the user hides two feeds it still shows 100 BUT I want it to show 60.

    I have also tried:

    PHP:
    - (int)countUnreadItems {
        
    NSFetchRequest *request = [[NSFetchRequest allocinit];
        [
    request setIncludesSubentities:YES];
        [
    request setEntity:[NSEntityDescription entityForName:@"FeedInfo" inManagedObjectContext:managedObjectContext]];
        
        
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@" (show = 1) AND (read = 0)"];
        [
    request setPredicate:predicate];
        
        
    NSError *err;
        
    NSUInteger count = [managedObjectContext countForFetchRequest:request error:&err];
        if(
    count == NSNotFound) {
            
    //Handle error
        
    }
            
        return 
    count;
    }  
    But get the following error:

    My question is, how can I adapt the above code to take into account the 'show' attribute with the least amount of overhead? Code examples would be good as I'm still trying to learn

    My entity diagram is attached.
     

    Attached Files:

  2. macrumors 6502

    seepel

    Joined:
    Dec 22, 2009
    #2
    Since show is a property of FeedInfo and read is a property of FeedItem, if your NSPredicate entity is FeedInfo you want
    Code:
    FeedItem.read = 0
    instead of
    Code:
    read = 0
     
  3. thread starter macrumors member

    Joined:
    Jul 21, 2010
    #3
    Thanks for the reply. So if I try the following should it work?

    PHP:
    (FeedInfo.show 1) AND (FeedItem.read 0)
    I ask because I did start to try it as per my first post but it gave the error that is also in that post.

    I also read today that you can't actually have a predicate across entities as you can only request one at a time. So is that true or is that avoided by having the relationship and NSSet in the object for FeedInfo?
     
  4. macrumors 6502

    seepel

    Joined:
    Dec 22, 2009
    #4
    It depends on which entity you are using in your predicate. So if you use FeedItem

    PHP:
    (FeedInfo.show 1) AND (read 0)
    and FeedInfo you want

    PHP:
    (show 1) AND (FeedItem.read 0)
    when you set the entity of the NSPredicate you are saying "Find me items from this pile that look like this." It won't know to go look in another pile of items unless you tell it to.
     
  5. thread starter macrumors member

    Joined:
    Jul 21, 2010
    #5
    So I have changed my code to the following as per the reply. I'm using FeedInfo and so used FeedItem.read

    PHP:
    - (int)countUnreadItems {
        
    NSFetchRequest *request = [[NSFetchRequest allocinit];
        [
    request setIncludesSubentities:YES];
        [
    request setEntity:[NSEntityDescription entityForName:@"FeedInfo" inManagedObjectContext:managedObjectContext]];
        
        
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@" (show = 1) AND (FeedItem.read = 0)"];
        [
    request setPredicate:predicate];

        
    NSError *err;
        
    NSUInteger count = [managedObjectContext countForFetchRequest:request error:&err];
        if(
    count == NSNotFound) {
            
    //Handle error
        
    }
            
        return 
    count;
    }
    However I still got the following error. Am I still doing something wrong that I am missing?

    If I take out ' AND (FeedItem.read = 0)' it works.
     
  6. macrumors 6502

    Joined:
    Jan 20, 2008
    #6
    Since you're goal is to count the number of items that are unread and being shown, it's probably better to form your fetch request around FeedItem. Use FeedItem as your entity name and form your predicate like:

    Code:
    
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(self.read == NO) AND (self.feedinfo.show == YES)"];
    
    
    This will only fetch feed items that have not been read and who's feedinfo is being shown.

    Also - note the use of the conditional (==) operator in the predicate and not the assignment (=) operator.
     
  7. macrumors 6502

    seepel

    Joined:
    Dec 22, 2009
    #7
    So I wasn't very careful when I read your mdel, you would want feeditems.read. The part before the dot should be the relationship name.
     

Share This Page