简体   繁体   中英

How to Delete a Managed Object When a Relationship Becomes Empty

I'm currently working on my first Core Data project for the iPhone. And after experimenting a little, I have some rather fundamental questions about entity relationships in core data.

Let's say I have two Entities: Event and Location. Each of them has a name attribute. An Event can only have one Location while a Location can have multiple Events. So the relationship would look like this:

Event <<--> Location

In my project I (the user) can type in the names for the Event and its Location. Then I'm creating a new object for the Event entity based on that input. I set the Location's name by accessing the Event's relationship like this:

event.Location.name = someCustomString;

Saving does work properly. I think.

My first question is:

Does Core Data create a new object for the Location entity every time I do this - even when the same Location name has been used before (and is still stored)? OR does Core Location automatically only set the relationship to an existing Location object in that case? Because for my project it is necessary to recognize Events that took place in the same location.

This also leads me to my next question:

What about deleting an Event object? When I do this I have to check if the corresponding Location is used by multiple Events. If it is, I'll nullify the relationship but keep the Location object. If not, I have to delete the Location object as well. My current approach (based on my assumption that Locations with the same name don't get double saved) looks like this:

Event *event = (event *)[appManager.results.fetchedObjects objectAtIndex:indexPath.row];

    NSInteger locationEvents = 0;

    for (Event *eve in appManager.results.fetchedObjects) 
    {
        if (eve.Location.name == event.Location.name) 
        {
            locationMoments++;
        }
    }

    if (locationMoments == 1) 
    {
        [appManager.managedObjectContext deleteObject:event.Location];
    }

    [appManager.managedObjectContext deleteObject:event];

So at least I think that I'm checking the number of events that a certain Location object refers to. But the code feels kind of itchy ... I don't know if that's the right approach. So my final question would be: What would be the standard procedure in my scenario? If there even is one. ;)

Thank you all in advance for your answers!!

Does Core Data create a new object for the Location entity every time I do this

No, event.Location.name is a keypath that is "walking" the relationship from the Event instance to the Location instance and then accessing the attribute name . A keypath only works for an existing object.

However, since you have one Location object shared with many Event objects, changing the Location.name value with any one Event object changes the value for all Event objects that share that Location object.

If you want a managed object to delete itself immediately when a relationship becomes empty, then put the delete code in the remove… accessor methods for the class. When the relationship hits zero, have the object tell the context to delete it. That lets you put the code in just one place instead of spread out everywhere you might change the relationship.

If you want to only delete the object when the context is saved, put the code in the class' willSave method. That will trigger a deletion when the context is next saved.

Thanks you very much for your help TechZen. Now I think I understand Core Data a little better. And I also got my Data Model working. Turns out that when I created my entities and the appropriate Subclasses I forgot to set the entity's classes to the created files in the Inspector. (Thought that would be set automatically - since the files were created automatically, too.) So the willSave method of my Location entities was never called. I fixed that and sorted out how to handle the relationships the right way. As I said I used a fetch request with a simple "name == %@" predicate to find previously used location names. ;)

But after all I'm using actual location data, too (Latitude, Longitude). And the coordinates of a Location will be slightly different, even if the Location and its name are the same. So I have to find a way to compare stored coordinates with the ones from the current user location. When the user is near a previously used location and uses that one's name, too - then the new coordinate data should override the old - OR it should just be left alone and the new Event gets assigned with the old Location. If you have any ideas on that, I'd be grateful, too! But I think I know what to do - mostly. :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM