Jamil
Jamil

Reputation: 940

Core Data: How to update value of type NSSet

I'm developing an application that allows user to draw routes on map. I have three entities:

My entities

User should be able to save Track, and then continue drawing it after a while. My problem is in updating - as i understood, to add Track objects to existing ones, i should fetch TrackName, update it's Set<Track> and save context(not sure about this one, is this right approach?). I store points that user draws in an array of custom type Line(it has same variable names as Track entity), but i don't know how to replace Set<Tracks> with Array<Line>. Is there any way to create array of type Track? Or can i add some kind of constructor for Track?

Right now i'm doing this:

var request = NSFetchRequest(entityName: "TrackName")
        var pred = NSPredicate(format: "name == %@ and username.userName == %@", trackName!, currentUser.login)
        request.predicate = pred
        request.returnsObjectsAsFaults = false

        var result : NSArray = NSArray()

        do
        {
             result = try context.executeRequest(request) as! [TrackName]
        }
        catch{}

        var currTrack = result[0] as! TrackName

and trying to do something like this

currTrack.track = Set<Track>(arrayLiteral: trackPoints)

but trackPoints is other type.

Edit 1.

Pavel, i tried to do it this way, but found out that new TrackName and Name objects were created each time, and when i fetch tracks added i get empty array. code below:

first, user names his track

func logName(name:String)
    {
        var appDel : AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate);
        var context : NSManagedObjectContext = appDel.managedObjectContext
        var nameEntity = NSEntityDescription.entityForName("Name", inManagedObjectContext: context)
        var forName = Name(entity: nameEntity!, insertIntoManagedObjectContext: context)
        forName.userName = currentUser.login

        var trackNameEntity = NSEntityDescription.entityForName("TrackName", inManagedObjectContext: context)
        var newTrack = TrackName(entity: trackNameEntity!, insertIntoManagedObjectContext: context)

        newTrack.name = name
        newTrack.username = forName
        do{
            try context.save()
        }
        catch{}
        trackName = name
    }

saving track:

func saveTrack()
    {
        var appDel : AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate);
        var context : NSManagedObjectContext = appDel.managedObjectContext

        var nameDesc = NSEntityDescription.entityForName("Name", inManagedObjectContext: context)
        var nameEnt = Name(entity: nameDesc!, insertIntoManagedObjectContext: context)
        nameEnt.userName = currentUser.login

        var trackNameDesc = NSEntityDescription.entityForName("TrackName", inManagedObjectContext: context)
        var trackEnt = TrackName(entity: trackNameDesc!, insertIntoManagedObjectContext: context)
        trackEnt.username = nameEnt
                 var trackDesc = NSEntityDescription.entityForName("Track", inManagedObjectContext: context)
        for p in trackPoints
        {
            var newTrack = Track(entity: trackDesc!, insertIntoManagedObjectContext: context)
            newTrack.trackname = trackEnt
            newTrack.startLat = p.startLat
            newTrack.startLon = p.startLon
            newTrack.endLat = p.endLat
            newTrack.endLon = p.endLon

        do {try context.save()}

        catch{}
    }
    }

When i save like this and check .sqlite file, i see that new Name and TrackName are created.

fetching:

func fetchWithPredicate(table: String, pred: NSPredicate)->NSArray
    {
        var appDel : AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate);
        var context : NSManagedObjectContext = appDel.managedObjectContext
        var request = NSFetchRequest(entityName: table)
        request.predicate = pred//NSPredicate(format: pred)
        request.returnsObjectsAsFaults = false
        var results: NSArray = NSArray()
        do{
            results = try context.executeFetchRequest(request)
        }

        catch{}

        return results
    }

fetchWithPredicate is called from here:

func getTrack(trackName: String)->[Track]
    {
        let pred = NSPredicate(format: "trackname.name == %@", trackName)
        return fetchWithPredicate("Track", pred: pred) as! [Track]
    }

it returns an empty array, but there are records in the .sqlite file

I think it's pretty much the same as you wrote. Am i doing something wrong here?

Upvotes: 0

Views: 1601

Answers (1)

Pavel Gatilov
Pavel Gatilov

Reputation: 2590

For the first one, to add new Track you don't need to add it manually to Set<Track>. Instead, you just need insert new Track object in context, then set for it TrackName, and then save context, and it will work just perfectly, it will automatically update TrackName entity.

And yes, you can create some category for Track which will insert it in context and take data from Line or trackPoints

Upvotes: 1

Related Questions