2017-02-16 51 views
7

В настоящее время я работаю над обновлением для уже существующего приложения (переход на Swift 3). У меня есть цели для Today-, Search-, Message- и Watch Extensions. Каждая цель должна получить доступ к базовой модели данных моего приложения, поэтому я создал AppGroup и включил возможность для каждой цели. Хотя я подклассы в NSPersistentStoreCoordinator, так что все хранится в общей папке:Swift3: Пустая выборка при доступе к основным данным из продления часов через AppGroups

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() 
    } 
} 

Этот класс-файл, а также мой Core-Data-модели и следующий класс являются все цели членства всех указанных целей. Кодек объектов установлен в Class Definition. До сих пор я использую реализацию по умолчанию для основных данных стека:

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)") 
      } 
     } 
    } 
} 

Теперь странная часть: Доступ к этой информации из Сегодня- и Message-Extension, кажется, работает корректно (я предполагаю поисково- Расширение тоже работает, но, насколько разработчик, я не могу это проверить). Попытка получить его с тем же запросом из расширения приложения Watch App в пустом массиве. Вот мой код выборки:

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 
    } 

Немного более контекст для лучшего понимания: POI Entitie содержит координаты широты и долготы местоположения. При запуске приложения я предварительно вычисляю расстояние до каждой точки в базе данных с позиции текущего пользователя. Когда Today-Extension пытается получить ближайшие POI-объекты x (в моем случае 8) в текущую позицию пользователя, выборка всех 15-килобайтовых POI и вычисление их расстояния - это разумная память. Поэтому мне пришлось предварительно рассчитать расстояние (хранящееся в locationDistanceCalculated), затем извлечь в заданном радиусе (статический SETTINGS_MAXIMUM_FETCH_DISTANCE) и рассчитать точное расстояние во время процесса выборки (сохранено в свойство переходного процесса locationDistanceTransient).

В Сторожевой приложения ExtensionDelegate Class A CLLocationManagerDelegate реализован и код называется, когда местоположение пользователя обновляется:

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) 
      } 
     } 
    } 
} 

Он был испытан в симуляторе и на устройстве. context.fetch всегда возвращает пустой массив (да, данные ядра содержат значения и да, я протестировал его без предиката). Я пропустил что-то новое в Core Data, которое я еще не рассматривал, или это их ограничения в WatchOS3, почему это не работает? Кто-нибудь знает? Спасибо за вашу помощь.

Обновление: при использовании целевой части Watch Framework для доступа к данным Core Data, как описано , выборка остается пустой. Возможно, это может быть правильный путь, но Watch Framework - неправильный выбор. Будет держать вас в курсе.

Update 2: Я уже проверил App Programming Guide для WatchOS и transferFile:metadata:function в API Ссылки, но это, кажется, не является подходящим способом отправить эти большие объемы данных в AppleWatch. Я просто не могу положиться на то обстоятельство, что пользователь проверяет приложение чаще, чем он выходит из радиуса SETTINGS_MAXIMUM_FETCH_DISTANCE, и для местоположений с высокой плотностью POI эти данные еще более обширны.

Обновление 3: Я переопределил функцию, предназначенную для объектов POI, чтобы получать только в заданном радиусе. Если это решает проблему для вас, ознакомьтесь с этой публикацией Gist.

ответ

2

Поскольку часы OS3, вы не можете получить доступ к CoreData базы с помощью App Group трюк (потому что часы должны работать без телефона.

Таким образом, вы должны использовать WatchConnectivity принести ваши данные

+0

Спасибо за ваш намек на WatchConnectivity, это близко к возможному решению, но не то, что я намеревался реализовать. Возможно, я дам ему попробовать и обернуть остальную реализацию вокруг него. Вы получите вознаграждение. – cr0ss

Смежные вопросы