逻辑错误的获取请求

时间:2017-01-14 03:01:52

标签: core-data swift3

我正在使用下面的块引用中提到的谓词执行获取请求,但我似乎得到了#34;逻辑错误的获取请求"。这条消息意味着什么,我应该采取什么步骤来找到问题并解决它?

  

注释:逻辑错误的获取请求(实体:国家;谓词:(" alpha3Code" ==" KOR"); sortDescriptors:((null)); type:NSManagedObjectResultType;)短路。

以下是我从

获取错误的代码
let record = Currency.fetch(id: currency)[0] as! Currency

其中Currency类如下。 "取"在NSManagedObjectProtocol trait中实现

public class Currency: NSManagedObject, NSManagedObjectProtocol, XMLImporterDelegate {

    private static let attributes = ["name", "currency", "decimalUnit", "isUsed"]
    private static let xmlRecordTag = "CcyNtry"
    private static let xmlAttributeTags = ["CcyNm": attributes[0],
                                           "Ccy": attributes[1],
                                           "CcyMnrUnts": attributes[2]]

    static func setValue(managedObject: NSManagedObjectProtocol, object: Dictionary<String, Any>) {
        let currency = managedObject as! Currency
        currency.name = getString(from: object, withKeyValue: attributes[0])
        currency.currency = getString(from: object, withKeyValue: attributes[1])
        currency.decimalUnit = getInt16(from: object, withKeyValue: attributes[2])
        currency.isUsed = getBool(from: object, withKeyValue: attributes[3])
        return
    }

    static func getPredicates(forID id: Dictionary<String, Any>) -> [NSPredicate] {
        var predicates: [NSPredicate] = []
        predicates.append(NSPredicate.init(format: "%@ = %@", attributes[1], getString(from: id, withKeyValue: attributes[1])))
        return predicates
    }

    func isEqual(object: NSManagedObjectProtocol) -> Bool {
        if let object = object as? Currency {
            if object.currency == self.currency { return false }
            return true
        } else {
            return false
        }
    }

    static func recordTag() -> String {
        return xmlRecordTag
    }

    static func attribute(byTag tag: String) -> String? {
        return xmlAttributeTags[tag]
    }

    static func getUsed() -> [Any]?{
        var predicates: [NSPredicate] = []
        predicates.append(NSPredicate.init(format: "%@ = %@", attributes[3], NSNumber(booleanLiteral: false)))
        return fetch(predicates: predicates)
    }
}

NSManagedObjectProtocol具有以下特征

extension NSManagedObjectProtocol {
    public static func add(from objectValue: Dictionary<String, Any>) -> NSManagedObjectProtocol? {
        let exists = fetch(id: objectValue)
        if exists.count > 0 {
            NSLog("Object already exists in CoreData : %@", objectValue.description)
            return nil
        } else {
            return newObject(object: objectValue)
        }
    }

    public static func addOrChange(from object: Dictionary<String, Any>) -> NSManagedObjectProtocol {
        let exists = fetch(id: object)
        if exists.count > 0 {
            // TODO: confirm if data needs to be changed rather than delete and insert
        }
        delete(id: object)
        return add(from: object)!
    }

    public static func getString(from object: Dictionary<String, Any>, withKeyValue key: String) -> String {
        return object[key] as! String
    }

    public static func getInt16(from object: Dictionary<String, Any>, withKeyValue key: String) -> Int16 {
        if let stringValue = object[key] as? String {
            if let intValue = Int(stringValue) {
                return Int16(intValue)
            } else {
                return 0
            }
        } else if let intValue = object[key] as? Int {
            return Int16(intValue)
        } else {
            return 0
        }
    }

    public static func getBool(from object: Dictionary<String, Any>, withKeyValue key: String) -> Bool {
        if let boolValue = object[key] as? Bool {
            return boolValue
        } else {
            return false
        }
    }

    public static func fetch(predicates: [NSPredicate] = [], sortDescriptors: [NSSortDescriptor] = []) -> [Any] {
        let request = Self.request(predicates: predicates)
        do {
            return try CoreDataHelper.getCoreDataHelper().context.fetch(request)
        } catch {
            return []
        }
    }

    public static func fetch(id: Dictionary<String, Any>) -> [Any] {
        return Self.fetch(predicates: Self.getPredicates(forID: id))
    }

    public static func delete(predicates: [NSPredicate] = []) {
        let context = CoreDataHelper.getContext()
        let fetchRequest = request(predicates: predicates)
        let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
        do {
            try context.execute(deleteRequest)
            CoreDataHelper.getCoreDataHelper().saveContext()
        } catch {
            NSLog("Delete request failed")
            return
        }
    }

    public static func delete(id: Dictionary<String, Any>) {
        delete(predicates: getPredicates(forID: id))
    }

    // MARK: - Private API
    private static func newObject(object: Dictionary<String, Any>) -> NSManagedObjectProtocol {
        let entityName = String(describing: self)
        let context = CoreDataHelper.getContext()
        let managedObject = NSEntityDescription.insertNewObject(forEntityName: entityName, into: context) as! NSManagedObjectProtocol
        setValue(managedObject: managedObject, object: object)
        CoreDataHelper.getCoreDataHelper().saveContext()
        return managedObject
    }

    private static func request(predicates: [NSPredicate] = [], sortDescriptors: [NSSortDescriptor] = []) -> NSFetchRequest<NSFetchRequestResult> {
        // Prepare a request
        let entityName = String(describing: self)
        let classObject: AnyClass! = NSClassFromString(entityName)
        let objectType: NSManagedObject.Type = classObject as! NSManagedObject.Type!
        let request: NSFetchRequest<NSFetchRequestResult> = objectType.fetchRequest()

        // Add predicates
        if predicates.count > 0 {
            request.predicate = NSCompoundPredicate.init(andPredicateWithSubpredicates: predicates)
        }

        // Add sortDescriptors
        if sortDescriptors.count > 0 {
            request.sortDescriptors = sortDescriptors
        }

        return request
    }
}

最后,这就是CoreDataHelper的样子。

class CoreDataHelper: NSObject {
    var context: NSManagedObjectContext!
    var model: NSManagedObjectModel!
    var coordinator: NSPersistentStoreCoordinator!
    var store: NSPersistentStore!
    let storeFilename = "Accounting.sqlite"

    func setupCoreData() {
        self.loadStore()
    }

    func saveContext() {
        if (self.context.hasChanges) {
            do {
                try context.save()
            } catch {

            }
        }
    }

    func applicationDocumentDictionary() -> String {
        let directory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last!
        NSLog("SQLite Directory : %@", directory)
        return directory
    }

    func applicationStoresDirectory() -> URL {
        let storesDirectory = URL.init(fileURLWithPath: self.applicationDocumentDictionary()).appendingPathComponent("Stores")
        let fileManager = FileManager.default
        if (!fileManager.fileExists(atPath: storesDirectory.path)) {
            do {
                try fileManager.createDirectory(at: storesDirectory,
                                                withIntermediateDirectories: true,
                                                attributes: nil)
            } catch {

            }
        }
        return storesDirectory
    }

    func storesURL() -> URL {
        return self.applicationStoresDirectory().appendingPathComponent(storeFilename)
    }

    override init() {
        super.init()
        model = NSManagedObjectModel.mergedModel(from: nil)
        coordinator = NSPersistentStoreCoordinator(managedObjectModel: model)
        context = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
        context.persistentStoreCoordinator = coordinator
    }

    func loadStore() {
        if (store != nil) {
            return
        } else {
            do {
                try store = coordinator.addPersistentStore(ofType: NSSQLiteStoreType,
                                                           configurationName: nil,
                                                           at: self.storesURL(),
                                                           options: nil)
            } catch {

            }
        }
    }

    static func getCoreDataHelper() -> CoreDataHelper {
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        return appDelegate.coreDataHelper
    }

    static func getContext() -> NSManagedObjectContext {
        return getCoreDataHelper().context
    }
}

只是为了让你知道Country类有alpha3Code。

extension Country {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Country> {
        return NSFetchRequest<Country>(entityName: "Country");
    }

    @NSManaged public var englishName: String?
    @NSManaged public var frenchName: String?
    @NSManaged public var alpha2Code: String?
    @NSManaged public var alpha3Code: String?
    @NSManaged public var countryNumber: Int16

}

1 个答案:

答案 0 :(得分:2)

使用建议的格式说明符%K作为密钥(路径)而非%@,如Predicate Documentation

中所述
predicates.append(NSPredicate.init(format: "%K = %@", attributes[1], getString(from: id, withKeyValue: attributes[1])))