Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to store an MKPolyline attribute as transformable in IOS coredata with swift?

What would be the code required to allow the storage of an MKPolyline in CoreData in swift.

So for example if I had one of my core data entities (say "myEntity") for which I wanted to save an MKPolyline, and have added the "polyline" field as transformable, and have set it to "transformable" in xcode. Also have produced NSManagedObject subclass.

myEntity.swift

import UIKit
import CoreData
import MapKit
class myEntity: NSManagedObject {
}

myEntity+CoreDataProperties.swift

import Foundation
import CoreData
extension myEntity {
    @NSManaged var title: String
    @NSManaged var polyline: NSObject? 
}

Question - What code is required to allow this to work?

( I do note this post re objective-c, however I'm struggling to understand/port/get this to work - How do you store data from NSMutable Array in Core Data? )

like image 937
Greg Avatar asked Apr 21 '16 06:04

Greg


People also ask

How do you use transformable core data?

To implement a Transformable attribute, configure it by setting its type to Transformable and specifying the transformer and custom class name in Data Model Inspector, then register a transformer with code before an app loads its Core Data stack.

What is Coredata in Swift iOS?

Core Data is a graphical and persistence framework, which is used in Apple devices with operating systems macOS and iOS. Core Data was first introduced in Mac OS X 10.4 Tiger and iOS with iPhone SDK 3.0.

Should I use Coredata?

The next time you need to store data, you should have a better idea of your options. Core Data is unnecessary for random pieces of unrelated data, but it's a perfect fit for a large, relational data set. The defaults system is ideal for small, random pieces of unrelated data, such as settings or the user's preferences.

Is Coredata a framework?

Core Data is a framework that you use to manage the model layer objects in your application. It provides generalized and automated solutions to common tasks associated with object life cycle and object graph management, including persistence.


1 Answers

Archive polyline object and save to Core Data:

    let context = self.fetchedResultsController.managedObjectContext
    let entity = self.fetchedResultsController.fetchRequest.entity!
    let newManagedObject = NSEntityDescription.insertNewObjectForEntityForName(entity.name!, inManagedObjectContext: context)
    let polylineObj = polyline() // For test purpose.
    let polylineData = polylineToArchive(polylineObj)
            newManagedObject.setValue(polylineData, forKey: "polyline")
        context.save()

Unarchive polyline from the NSManagedObject:

    let object = self.fetchedResultsController.objectAtIndexPath(indexPath) as! NSManagedObject
    let data = object.valueForKey("polyline") as! NSData
    let polyline = polylineUnarchive(data)
    log(polyline!)

MKPolyline arhiver and unarchiver functions. As well some helper functions.

func polylineUnarchive(polylineArchive: NSData) -> MKPolyline? {
    guard let data = NSKeyedUnarchiver.unarchiveObjectWithData(polylineArchive),
        let polyline = data as? [Dictionary<String, AnyObject>] else {
        return nil
    }
    var locations: [CLLocation] = []
    for item in polyline {
        if let latitude = item["latitude"]?.doubleValue,
            let longitude = item["longitude"]?.doubleValue {
            let location = CLLocation(latitude: latitude, longitude: longitude)
            locations.append(location)
        }
    }
    var coordinates = locations.map({(location: CLLocation) -> CLLocationCoordinate2D in return location.coordinate})
    let result = MKPolyline(coordinates: &coordinates, count: locations.count)
    return result
}

func polylineToArchive(polyline: MKPolyline) -> NSData {
    let coordsPointer = UnsafeMutablePointer<CLLocationCoordinate2D>.alloc(polyline.pointCount)
    polyline.getCoordinates(coordsPointer, range: NSMakeRange(0, polyline.pointCount))
    var coords: [Dictionary<String, AnyObject>] = []
    for i in 0..<polyline.pointCount {
        let latitude = NSNumber(double: coordsPointer[i].latitude)
        let longitude = NSNumber(double: coordsPointer[i].longitude)
        let coord = ["latitude" : latitude, "longitude" : longitude]
        coords.append(coord)
    }
    let polylineData = NSKeyedArchiver.archivedDataWithRootObject(coords)
    return polylineData
}

func polyline() -> MKPolyline {
    let locations = [CLLocation(latitude: 37.582691, longitude: 127.011186), CLLocation(latitude: 37.586112,longitude: 127.011047), CLLocation(latitude: 37.588212, longitude: 127.010438)]
    var coordinates = locations.map({(location: CLLocation) -> CLLocationCoordinate2D in return location.coordinate})
    let polyline = MKPolyline(coordinates: &coordinates, count: locations.count)
    return polyline
}

func log(polyline: MKPolyline) {
    let coordsPointer = UnsafeMutablePointer<CLLocationCoordinate2D>.alloc(polyline.pointCount)
    polyline.getCoordinates(coordsPointer, range: NSMakeRange(0, polyline.pointCount))
    var coords: [Dictionary<String, AnyObject>] = []
    for i in 0..<polyline.pointCount {
        let latitude = NSNumber(double: coordsPointer[i].latitude)
        let longitude = NSNumber(double: coordsPointer[i].longitude)
        let coord = ["latitude" : latitude, "longitude" : longitude]
        coords.append(coord)
    }
    print(coords)
}
like image 102
Ramis Avatar answered Oct 02 '22 12:10

Ramis