Sarang Borude
Sarang Borude

Reputation: 329

How to convert MKMapItem to binary data to store in Core Data?

I am want to store MKMapItem that was previously found by MKLocalSearch in Core Data so I can show it to the user when the view loads in the future.

What I have is I have created an Entity in xcdatamodeld file and created a binaryData attribute called mapItem.

I want to encode the found MKMapItem to binary data and store it in core data.

Later I want to decode it to an MKMapItem.

I noticed that MKMapItem has an encode method that needs an NSCoder object.

I am not super familiar with NSCoding so any help will be appreciated.

I can always save the string attributes from MKMapItem in core data by creating multiple attributes for the entity, but I was wondering if there was an easy way.

Thanks!

Upvotes: 0

Views: 448

Answers (1)

Sarang Borude
Sarang Borude

Reputation: 329

I figured it out. To store the MapItem in Core Data, I used the NSKeyedArchiver. It encodes the MapItem into Data and to decode, you can use the NSKeyedUnarchiver

func saveMapItems(_ mapItems: [MKMapItem]) {
    do {
        let data = try NSKeyedArchiver.archivedData(withRootObject: mapItems, requiringSecureCoding: false)
        let request: NSFetchRequest<RecentSearchLocation> = RecentSearchLocation.fetchRequest()
        if
            let recentLocations = try? coreDataManager.persistentContainer.viewContext.fetch(request).first,
            let location = recentLocations {
            location.mapItems = data
        } else {
            let location = RecentSearchLocation(context: coreDataManager.persistentContainer.viewContext)
            location.mapItems = data
        }
    } catch {
        print("Can't encode data: \(error)")
    }
    do {
        try coreDataManager.persistentContainer.viewContext.save()
    } catch {
        print("Error saving context \(error)")
    }
}

To decode I did this

func readMapItems() -> [MKMapItem] {
        let request: NSFetchRequest<RecentSearchLocation> = RecentSearchLocation.fetchRequest()
        guard
            let data = try? coreDataManager.persistentContainer.viewContext.fetch(request).first?.mapItems,
            let dataToUnarchive = data else {
                print("Cannot get mapItems from coreData data")
                return []
        }
        do {
            guard let recentSearchLocations = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(dataToUnarchive) as? [MKMapItem] else {
                return []
            }
            return recentSearchLocations
        } catch {
            print("Error unarchiving mapItems, \(error)")
            return []
        }
    }

Upvotes: 1

Related Questions