Сохранение Swift CLLocation в CoreData
Я пытаюсь спасти CLLocation
данные в основных данных. Мое свойство установлено как Преобразуемый объект.
Некоторые примеры кода показывают, что можно сохранить данные о местоположении, используя этот объект, преобразованный в NSValue
,
CLLocationCoordinate2D myLocation;
NSValue *locationValue = [NSValue valueWithBytes:&myLocation objCType:@encode(CLLocationCoordinate2D)]
// then put locationValue into storage - maybe an ObjC collection class or core data etc.
Получение объекта из хранилища данных должно работать с использованием этой парадигмы.
CLLocationCoordinate2D myLocation;
NSValue *locationValue = // restored from your database or retrieved from your collection class
[locationValue getValue:&myLocation];
Я пытаюсь экстраполировать эту идею и охватить всю CLLocation
возражать в NSValue
Хранится в CoreData
с целью восстановить CLLocation
Объект из магазина в более позднее время.
При тестировании различных методов я обнаружил, что при попытке развернуть CLLocation
объект из основного хранилища данных. Я размещаю CLLocation
Объект в магазин, используя следующее:
//verified that I have a good CLLocation here
newManagedObject.setValue(location as CLLocation, forKey: "location")
Позже я пытаюсь развернуть CLLocation
let location = detail.valueForKey("location")! as CLLocation
Но я считаю, что объект не разворачивается должным образом.
Развернутый объект выглядит так:
(CLLocation) location = 0x00007fff59537c90 {
ObjectiveC.NSObject = {}
}
Так что любое использование CLLocation
объект в этот момент возвращает "найдена ноль... ошибка"
Я упускаю что-то очевидное о хранении / получении CLLocation
объекты, использующие Swift?
ОБНОВИТЬ
Ответ Даниэля помог мне понять, что NSValueTransformer не будет работать на меня, поэтому я вернулся к подходу, который использовал ранее. В основном кодируйте объектный граф, используя NSKeyedArchiver. Моя цель, как всегда, состоит в том, чтобы использовать самое простое из возможных решений, поэтому я решил не использовать подклассы управляемых объектов, поскольку нужные мне свойства уже находятся в существующем объекте CLLocation. Я изменил трансформируемое поле на Двоичные данные с выбранной опцией (Сохранить во внешнем файле записи). Я решил протестировать этот процесс с минимальными изменениями в шаблоне основных деталей.
Сохранение графа объекта CLLocation
//assuming location is a valid CLLocation and data model has a binary data field
let archivedLocation = NSKeyedArchiver.archivedDataWithRootObject(location)
newManagedObject.setValue(archivedLocation, forKey: "location")
Восстановление графа объекта из хранилища данных
На основном vc как часть подготовки по умолчанию к segue данные восстанавливаются через контроллер выборки.
let object = self.fetchedResultsController.objectAtIndexPath(indexPath) as NSManagedObject
let controller = (segue.destinationViewController as UINavigationController).topViewController as DetailViewController
controller.detailItem = object
На подробностях vc я разворачиваю свой граф объектов, используя NSKeyedUnarchiver
var lc = NSKeyedUnarchiver.unarchiveObjectWithData(detail.valueForKey!("location") as NSData) as CLLocation
2 ответа
Что вам не хватает, так это то, что NSValue предназначен для хранения типов, т. Е. Смежных блоков памяти, а не объектов. CLLocation - это объект.
Чтобы сохранить CLLocation в основных данных, вам нужно будет сохранить каждое из свойств. Альтернатива - использовать кодер.
У вас будет гораздо меньше проблем, когда вы создадите NSManagedObject
подкласс для CLLocation
объекты. Затем создайте методы для хранения и извлечения для удобства:
import Foundation
import CoreData
import CoreLocation
class LocationPoint: NSManagedObject {
@NSManaged var latitude: NSNumber!
@NSManaged var longitude: NSNumber!
@NSManaged var altitude: NSNumber!
@NSManaged var timestamp: NSDate!
@NSManaged var horizontalAccuracy: NSNumber
@NSManaged var verticalAccuracy: NSNumber
@NSManaged var speed: NSNumber
@NSManaged var course: NSNumber
func initFromLocation(location: CLLocation) {
self.latitude = location.coordinate.latitude
self.longitude = location.coordinate.longitude
self.altitude = location.altitude
self.timestamp = location.timestamp
self.horizontalAccuracy = location.horizontalAccuracy > 0.0 ? location.horizontalAccuracy : 0.0
self.verticalAccuracy = location.verticalAccuracy > 0.0 ? location.verticalAccuracy : 0.0
self.speed = location.speed > 0.0 ? location.speed : 0.0
self.course = location.course > 0.0 ? location.course : 0.0
}
func location() -> CLLocation {
return CLLocation(
coordinate: CLLocationCoordinate2D(latitude: self.latitude.doubleValue, longitude: self.longitude.doubleValue),
altitude: self.altitude.doubleValue,
horizontalAccuracy: self.horizontalAccuracy.doubleValue,
verticalAccuracy: self.verticalAccuracy.doubleValue,
course: self.course.doubleValue,
speed: self.speed.doubleValue,
timestamp: self.timestamp
)
}
Вы должны настроить свою модель данных с сущностью в соответствии с этим классом.
Этот пост все еще полезен, но немного устарел.
Для сохранения CLLocation я использую:
let clocation: [CLLocation]
let archivedLocation = NSKeyedArchiver.archivedData(withRootObject: clocation)
И получить с помощью основных данных:
let unarchivedLocation = NSKeyedUnarchiver.unarchiveObject(with: (coreDataLocation.value(forKey: "location") as! NSData) as Data) as! CLLocation)