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!
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 []
}
}