paulw11 / Seam3

Cloudkit based persistent store for Core Data
Other
209 stars 25 forks source link

Could not cast value of type 'NSKnownKeysDictionary1' to 'NSManagedObject' #41

Closed DJ-Glock closed 7 years ago

DJ-Glock commented 7 years ago

Hey Paul! I have found another issue.

CoreData Entity:

2017-09-23 21 30 53

Function that gets popular names:

    class func getPopularGuests () -> [String] {
        var popularGuestNames: [String] = []
        let keypathExp = NSExpression(forKeyPath: "guestName")
        let expression = NSExpression(forFunction: "count:", arguments: [keypathExp])

        let countDesc = NSExpressionDescription()
        countDesc.expression = expression
        countDesc.name = "count"
        countDesc.expressionResultType = .integer64AttributeType

        let request = NSFetchRequest<NSDictionary>(entityName: "GuestsTable")
        request.predicate = NSPredicate(format: "NOT guestName CONTAINS[cd] %@", NSLocalizedString("guestNameForInsert", comment: ""))
        request.returnsObjectsAsFaults = false
        request.propertiesToGroupBy = ["guestName"]
        request.propertiesToFetch = ["guestName", countDesc]
        request.resultType = .dictionaryResultType
        var matchedGuests = [[String:Any]]()
        if let result = try? context.fetch(request) as! [[String:Any]] {
            matchedGuests = result
        }
        var sortedGuests = [[String:Any]]()
        sortedGuests = matchedGuests.sorted(by: {$0["count"] as! Int > $1["count"] as! Int})
        guard sortedGuests.count != 0 else {return popularGuestNames}
        var limit = 10
        if sortedGuests.count <= limit {
            limit = sortedGuests.count - 1
        }
        for index in 0...limit {
            popularGuestNames.append(sortedGuests[index]["guestName"] as! String)
        }
        return popularGuestNames
    }

And it's failing here:

    // MARK : Fetch Request
    func executeInResponseToFetchRequest(_ fetchRequest:NSFetchRequest<NSFetchRequestResult>,context:NSManagedObjectContext) throws ->[NSManagedObject] {
        let resultsFromLocalStore = try self.backingMOC.fetch(fetchRequest)
        if !resultsFromLocalStore.isEmpty {
            return resultsFromLocalStore.map({(result)->NSManagedObject in
                let result = result as! NSManagedObject // Fails here
                let recordID: String = result.value(forKey: SMStore.SMLocalStoreRecordIDAttributeName) as! String
                let entity = self.persistentStoreCoordinator?.managedObjectModel.entitiesByName[fetchRequest.entityName!]
                let objectID = self.newObjectID(for: entity!, referenceObject: recordID)
                let object = context.object(with: objectID)
                return object
            })
        }
        return []
    }

Output:

Sync Performed Sync performed successfully Could not cast value of type 'NSKnownKeysDictionary1' (0x1097f1068) to 'NSManagedObject' (0x1097f1310). (lldb) po result ▿ 2 elements ▿ 0 : 2 elements

  • key : guestName
  • value : James ▿ 1 : 2 elements ▿ key : count
  • value : 2

(lldb)

SS:

2017-09-23 21 34 00

I believe Seam3 does not support dictionaryResultType. As a workaround I have changed function to get recently used guest names without complicated calculations. But if it's possible to fix it in Seam3, it will be brilliant. I believe it's feature request.