Search code examples
iosarraysjsonswiftnsmanagedobjectcontext

Comparing NSManagedObjects to contents of a JSON array


I have a managedObjectContext that I initially populate with the contents of a JSON file.

The first couple of versions were pretty easy to update the managedObjectContext for new content, but as the number of versions has grown, it's getting tough to feed a filename of stuff to update across various versions.

What I'm trying to do is use the currentVersionJSON as a Rosetta stone to determine what should in the managedObjectContext and what should be deleted. I've got the "additions" via JSON figured out, but I'm having difficulty going the other way to remove old stuff from the managedObjectContext.

I've figured out the adding records to the managedObjectContext based on the JSON file's contents by creating a predicate based on the JSON entry and if it doesn't exist, I add it.

Going the other way hasn't been as easy. Basically, what I'm trying to do is the following:

1) Create an array of mocItems which has the contents of the managedObjectContext

2) Create an array of jsonItems which has the contents of the currently shipping version

3) If an item is in the managedObjectContext isn't in jsonItems, append it to a list of objects to delete.

Right now, it doesn't crash, but it just runs and runs and runs. I'm out of my depth in terms of resolving it. I'd like to avoid adding CocoaPods, as I'd have to go through and refactor a bunch of stuff when I'd rather get on down the road. Any feedback re: what I'm mucking up would be greatly appreciated.

    do {

        // Get all items in MOC
        var mocItems = [Item]()

        // Initialize a fetchRequest
        let fetchRequest = NSFetchRequest()

        // Tell what entity you want to search
        let entityDescription = NSEntityDescription.entityForName("Item", inManagedObjectContext: self.managedObjectContext)
        fetchRequest.entity = entityDescription

        // Execute fetch and assign arrayOfItems to it
        do {
            mocItems = try managedObjectContext.executeFetchRequest(fetchRequest) as! [Item]
        } catch {
            // failure
            print("Fetch failed: \(error)")
        }

        // Get the list of items from the currently shipping version
        // Tell where the data is located
        let jsonData = NSData(contentsOfURL: itemsToAddURL!)

        var jsonItems = NSArray()

        // Create an array to dump data from JSON file into
        do {
            jsonItems = try NSJSONSerialization.JSONObjectWithData(jsonData!, options: NSJSONReadingOptions.MutableContainers) as! NSArray

        } catch {
            print("json error: \(error)")
        }

        for item in jsonItems {

            let itemDescription = item.valueForKey("itemDescription") as! String

            for object in mocItems {
                if itemDescription != object.itemDescription {
                    itemsToDelete.append(object)
                }
            }
        } 
    }

Solution

  • Thanks to Wain for pointing me in the right direction. The solution to my issue was startlingly simple.

    I broke my problem up in 3 sections:

    1) get items from the managedObjectContext

    2) pulling out the itemDescriptions of items for the current version's JSON file that I created and dump the Strings into an Array for comparison.

    I found this answer particularly helpful:

    https://stackoverflow.com/a/31859336/4475605

    3) compare each item in managedObjectContext to the current version's JSON contents.

    I was fouling up step 2 and step 3. Here's what they look like now:

    func deleteItems() {
    
        // Create a landing spot for data from MOC & list of items in current version
        // All the items in the MOC
        var mocItems = [Item]()
        var itemsToDelete = [Item]()
    
        // Name of items from the current version
        var itemNamesArray = [String]()
    
        do {
            // Initialize a fetchRequest
            let fetchRequest = NSFetchRequest()
    
            // Tell what entity you want to search
            let entityDescription = NSEntityDescription.entityForName("Item", inManagedObjectContext: self.managedObjectContext)
            fetchRequest.entity = entityDescription
    
            // Execute fetch and assign mocItems to it
            do {
                mocItems = try managedObjectContext.executeFetchRequest(fetchRequest) as! [Item]
            } catch {
                // failure
                print("Fetch failed: \(error)")
            }
        }
    
        // Get the list of items from the currently shipping version
        // Tell where the data is located
        let jsonData = NSData(contentsOfURL: itemsToAddURL!)
    
        var jsonItems = NSArray()
    
        // Create an array to dump data from JSON file into
        do {
            jsonItems = try NSJSONSerialization.JSONObjectWithData(jsonData!, options: NSJSONReadingOptions.MutableContainers) as! NSArray
        } catch {
            print("json error: \(error)")
        }
    
        for item in jsonItems as! [Dictionary<String, AnyObject>] {
            let itemDescription = item["itemDescription"] as! String
            itemNamesArray.append(itemDescription)
        }
    
        for item in mocItems {
            if itemNamesArray.contains(item.itemDescription) {
                // keep it
            } else {
                itemsToDelete.append(item)
            }
        }
    
        for item in itemsToDelete {
            managedObjectContext.deleteObject(item)
            saveContext()
        }
    }