ios - Swift3: vaciar la búsqueda al acceder a los datos principales de Watch Extension a través de AppGroups
core-data watch-os-3 (1)
Actualmente estoy trabajando en una actualización para una aplicación ya existente (migración a Swift 3). Tengo objetivos para Today, Search, Message y Watch Extensions. Cada objetivo debe acceder al Modelo de Datos Básicos de mi Aplicación, así que creé un Grupo de Aplicaciones y habilité la Capacidad para cada objetivo. Aunque he subclasificado el NSPersistentStoreCoordinator, entonces todo está almacenado en una carpeta compartida:
import CoreData
class PFPersistentContainer: NSPersistentContainer {
override open class func defaultDirectoryURL() -> URL {
if let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "add-groupname-here") {
return url
}
// Fallback
return super.defaultDirectoryURL()
}
}
Este archivo de clase, así como mi Core-Data-Model y la siguiente clase pertenecen todos a objetivos de todos los objetivos mencionados. El Codegen de las Entidades está configurado en Class Definition
. Hasta ahora, estoy usando la implementación predeterminada para la Pila de datos básicos:
class DataManager {
/**
* Singleton Implementation
*/
internal static let sharedInstance:DataManager = {
let instance = DataManager()
return instance
}()
// MARK: - Core Data stack
lazy var persistentContainer: PFPersistentContainer = {
let container = PFPersistentContainer(name: "Data")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error /(error), /(error.userInfo)")
}
})
return container
}()
// MARK: - Core Data Saving support
func saveContext () {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
let nserror = error as NSError
fatalError("Unresolved error /(nserror), /(nserror.userInfo)")
}
}
}
}
Ahora la parte más extraña: acceder a estos datos desde la extensión de hoy y de mensaje parece funcionar con gracia (supongo que la búsqueda-extensión también está funcionando, pero por lo que respecta a un desarrollador, no puedo probar esto). Intentar buscarlo con la misma Solicitud desde la Extensión de la aplicación Watch resulta en una Matriz vacía. Aquí está mi código de búsqueda:
internal func getLimitedPOIsWithCalculatedDistance(andCurrentLocation currentLocation:CLLocation) -> Array<POI> {
var poiArray:Array< POI > = []
guard let context = self.backgroundContext else { return [] }
do {
// Initialize Fetch Request
let request:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "POI")
// Create Entity Description
let entityDescription = NSEntityDescription.entity(forEntityName: "POI", in: context)
// Configure Fetch Request
request.entity = entityDescription
// Configure Predicate
let predicate = NSPredicate(format: "(disabled == NO) AND (locationDistanceCalculated <= /(SETTINGS_MAXIMUM_FETCH_DISTANCE))")
request.predicate = predicate
if let result = try context.fetch(request) as? Array<POI> {
for poi in result {
let poiLocation = CLLocation(latitude: poi.locationLatitude, longitude: poi.locationLongitude)
let distance = currentLocation.distance(from: poiLocation)
poi.locationDistanceTransient = Double(distance)
}
poiArray = result.filter({ (poi) -> Bool in
return poi.locationDistanceTransient > 0.0
})
poiArray.sort { (first, second) -> Bool in
return first.locationDistanceTransient < second.locationDistanceTransient
}
}
} catch {
print("Error in WatchDataInterface.getLimitedPOIsWithCalculatedDistance(): /(error.localizedDescription)")
}
return poiArray
}
Un poco más de contexto para una mejor comprensión: la entidad POI contiene latitud y longitud de una ubicación. Al iniciar la aplicación, estoy calculando previamente la distancia a cada punto de la base de datos desde la posición del usuario actual. Cuando Today-Extension intenta obtener los puntos de interés de x (en mi caso 8) más cercanos a la posición actual de los usuarios, obtener todos los 15k POI y calcular su distancia es una cuestión de memoria. Así que tuve que calcular previamente la distancia (almacenada en la
locationDistanceCalculated
), luego buscar en un radio determinado (SETTINGS_MAXIMUM_FETCH_DISTANCE
estático) y calcular una distancia precisa durante el proceso de recuperación (almacenado en unalocationDistanceTransient
propiedad transitoriaDistanceTransient).
En la clase ExtensionDelegate
Watch App, se implementa CLLocationManagerDelegate
se CLLocationManagerDelegate
el código cuando se actualiza la ubicación del usuario:
extension ExtensionDelegate: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
OperationQueue.main.addOperation{
if let watchDataManager = self.watchDataManager {
// getNearestPOIs() calls the getLimitedPOIsWithCalculatedDistance() function and returns only a numberOfPOIs
self.nearbyPOIs = watchDataManager.getNearestPOIs(numberOfPOIs: 4)
}
}
}
}
Fue probado en simulador y en un dispositivo. The context.fetch
siempre devuelve una matriz vacía (Sí, los datos centrales contienen valores y sí, los he probado sin el predicado). ¿Me falta algo nuevo en Core Data, que aún no he considerado o son sus limitaciones en WatchOS3 por qué esto no funciona? ¿Alguien tiene una pista? Gracias por tu ayuda.
Actualización: cuando se utiliza un objetivo de Watch Framework para acceder a Core Data, como se describe en este proyecto , la búsqueda permanece vacía. Tal vez este podría ser el camino correcto, pero un Marco de vigilancia es la selección incorrecta. Te mantendré al día.
Actualización 2: Ya revisé la Guía de programación de aplicaciones para WatchOS y la función transferFile:metadata:
en las referencias de API, pero no parece ser una forma adecuada de enviar estas grandes cantidades de datos al AppleWatch. Simplemente no puedo confiar en la circunstancia de que el usuario esté revisando la aplicación con más frecuencia de lo que está viajando fuera del radio SETTINGS_MAXIMUM_FETCH_DISTANCE
y para las ubicaciones con una alta densidad de puntos de interés, esta información es aún más extensa.
Actualización 3: He vuelto a implementar la característica cercana para los POIs para buscar solo en un radio dado. Si esto te soluciona un problema, mira este Gist público.
Desde Watch OS3, no puede acceder a una base CoreData
utilizando el truco del grupo de aplicaciones (porque se supone que el reloj debe funcionar sin un teléfono.
Entonces debes usar WatchConnectivity
para buscar tus datos