1

I have a very weird problem that has stumped me rather!

I have a core data entity that i have just added some new attributes to:

deleted - Boolean deletedDate - Date

I have the following code, that upon pressing sets both those values on the core data object:

- (IBAction)deleteButtonInTable:(id)sender {


    //Get the ID of the currently selected item in the table
    NSInteger selected = [self.tweetTableView rowForView:sender];

    //Create a predicate and fetch the objects from Core Data
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSPredicate *testForTrue = [NSPredicate predicateWithFormat:@"approved == NO"];
    NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"postDate"  ascending:NO];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, nil];
    [request setPredicate:testForTrue];
    [request setSortDescriptors:sortDescriptors];

    [request setEntity:[NSEntityDescription entityForName:@"Tweet" inManagedObjectContext:_managedObjectContext]];

    //Setup the Request
    [request setEntity:[NSEntityDescription entityForName:@"Tweet" inManagedObjectContext:_managedObjectContext]];

    //Assign the predicate to the fetch request
    NSError *error = nil;

    //Create an array from the returned objects
    NSArray *fetchedObjects = [_managedObjectContext executeFetchRequest:request error:&error];

    Tweet *selectedTweet = [fetchedObjects objectAtIndex:selected];

    if (selectedTweet) {
        selectedTweet.deleted = [NSNumber numberWithBool:TRUE];
        selectedTweet.deletedDate = [NSDate date];
        NSLog(@"%@",selectedTweet);
        [self refreshTableView];
        if (! self.tweetTableView){
            NSLog(@"Tableview doesn't exist!!)");
        }
        [[self tweetTableView] reloadData];
        [[self managedObjectContext] commitEditing];
        [self saveAction:nil];
    }

    if ([self.autoWriteTweets isEqualToString:@"YES"]){
        [self writeTweetsToXML];
        [self saveAction:nil];
    }
}

Now, if i watch the object in xcode with some breaks, i can see the attribute change on the object as i pass through the function, but i have an Table displaying a datasource, which is filtered to only show objects that have the deleted bool set to true, and nothing ever shows up there.

Now, to make things even more confusing i have a function that exports an array of the objects:

-(void)writeTweetsToXML{
    //Create new fetch request
    NSFetchRequest *request = [[NSFetchRequest alloc] init];

    //Set new predicate to only fetch tweets that have been favourited
    NSPredicate *filterFavourite = [NSPredicate predicateWithFormat:@"approved == YES"];
    NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:self.exportSort ascending:NO];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, nil];
    [request setSortDescriptors:sortDescriptors];

    //Setup the Request
    [request setEntity:[NSEntityDescription entityForName:@"Tweet" inManagedObjectContext:_managedObjectContext]];
    [request setResultType:NSDictionaryResultType];

    //Assign the predicate to the fetch request
    [request setPredicate:filterFavourite];
    NSError *error = nil;

    //Create an array from the returned objects
    NSArray *tweetsToExport = [_managedObjectContext executeFetchRequest:request error:&error];
    NSAssert2(tweetsToExport != nil && error == nil, @"Error fetching events: %@\n%@", [error localizedDescription], [error userInfo]);


     //NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    //NSString *path = [NSString stringWithFormat:@"%@/tweets.xml", documents];
NSString *writeerror;

    if(tweetsToExport) {
        NSString * exportLocationFull = [[NSString alloc]initWithFormat:@"%@/tweets.xml",self.exportLocation];
        BOOL success = [tweetsToExport writeToFile:exportLocationFull atomically:YES];
        NSLog(@"Write Status = %d to %@", success, exportLocationFull);
    }
    else {
        NSLog(@"%@",writeerror);

    }


}

Now, when i look at the exported file, two things happen which are odd!

Firstly, an object that i have seen have it's deleted value set to true, exports with the value as 0.

Secondly, the deletedDate attribute does not export at all, every, despite it being in the core data model. I can't see any way this can happen as i am doing no specific filtering on the export.

It's like a getter/setter somewhere is broken, but i have checked the class files and everything is as it should be and set to @dynamic.

Any help would be greatly appreciated as i'm a bit lost as to what the hell is going on.

People had warned me about core data's quirks, but this is just plain odd!

Cheers

Gareth

Note 1

As an aside, i am using the exact same code from the first section to set other attributes on objects that are filtered and that seems to work fine!

Gareth Jeanne
  • 1,410
  • 2
  • 19
  • 35
  • Compare http://stackoverflow.com/questions/16000242/core-data-nspredicate-predicatewithblock-and-predicatewithformat-in-parent-child - You should not call an attribute "deleted". – Martin R Jul 25 '13 at 14:51
  • Hi Martin, this was exactly it, DOH!!!!! Can you post it as an answer and i will select it. Can't believe how long i spent on that! – Gareth Jeanne Jul 25 '13 at 16:27

3 Answers3

1

You should not name an Core Data attribute "deleted", that conflicts with the isDeleted method of NSManagedObject.

Compare https://stackoverflow.com/a/16003894/1187415 for a short analysis of that problem.

There are other attribute names that cause conflicts, e.g. "updated" (compare Cannot use a predicate that compares dates in Magical Record). Unfortunately, there are no warnings at compile time or runtime, and the documentation on what acceptable attribute names are is also quite vague.

Community
  • 1
  • 1
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
0

Things to check:

  1. Did you save your core data entities with [managedObjectContext save:&error] at the appropriate places (e.g. before displaying the new table view data)? Did you check the error variable?

  2. Did you migrate your model correctly with a new model version?

  3. Are you reading the correct attributes and displaying them correctly (in UI or log statements)?

BTW, in your code you are setting the request entity twice.

Mundi
  • 79,884
  • 17
  • 117
  • 140
0

Try saving the mananged object context before loading the table view.

The boolean deleted may be 0 before and not be changed or it may be auto-initialized (there is an field in the inspector to set default values) to 0. Date fields on the other hand are nil by default.

P.S. Use [NSNumber numberWithBoolean:YES] in Objective-C.

Paul
  • 999
  • 1
  • 12
  • 29