簡體   English   中英

Swift3:通過AppGroups從Watch Extension訪問Core Data時的空提取

[英]Swift3: Empty fetch when accessing Core Data from Watch Extension via AppGroups

目前我正在為已有的App(遷移到Swift 3)進行更新。 我有針對Today-,Search-,Message-和Watch Extensions的目標。 每個目標都需要訪問我的應用程序的核心數據模型,因此我創建了一個AppGroup並為每個目標啟用了Capability。 雖然我已經將NSPersistentStoreCoordinator子類化,但所有內容都存儲在共享文件夾中:

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-Model和下面的類都是所有提到的目標的目標成員。 實體的Codegen設置為Class Definition 到目前為止,我正在使用Core Data Stack的默認實現:

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

現在奇怪的部分:從Today-和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嘗試將最接近的x(在我的情況下為8)POI提供給當前用戶位置時,獲取所有15k POI並計算它們的距離對於記憶很大。 所以我必須預先計算距離(存儲在locationDistanceCalculated ),然后在給定半徑內獲取(靜態SETTINGS_MAXIMUM_FETCH_DISTANCE )並在獲取過程中計算精確距離(存儲到瞬態屬性locationDistanceTransient )。

在Watch App的ExtensionDelegate類中,當用戶位置更新時,將實現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時,就像在此項目中描述的那樣 ,fetch保持為空。 也許這可能是正確的道路,但Watch Framework是錯誤的選擇。 會讓你保持最新。

更新2:我已經檢查了WatchOS的App編程指南和API參考中的transferFile:metadata: 函數 ,但它似乎不是將這些大量數據發送到AppleWatch的合適方式。 我不能依賴於這樣的情況:用戶正在檢查應用程序的頻率高於他在SETTINGS_MAXIMUM_FETCH_DISTANCE范圍之外的距離,對於具有高密度POI的位置,此數據甚至更廣泛。

更新3:我重新實現了附近的POI功能,只能在給定的半徑內獲取。 如果這為您解決了問題,請查看此公開要點

從Watch OS3開始,您無法使用App Group技巧訪問CoreData基礎(因為手表應該在沒有手機的情況下工作。

因此,您必須使用WatchConnectivity來獲取數據

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM