一对多关系查询的NSPredicate示例

时间:2018-08-24 19:54:55

标签: swift core-data xcode9

This is my core data model

关系如下: enter image description here

这种关系是通往多个位置的一条路线。第一个问题是位置中是否应该有名称属性(routeName)?例如,在DB2中,您总是命名主键,但是我在Core Data中看到的大多数示例都在关系定义的幕后处理主键。

这是来自DB Browser的sqlite摘录。

Table Excerpts

代码如下:

    final class CoreDataManager {

static let sharedInstances = CoreDataManager()

let managedContext: NSManagedObjectContext

private init(){
    let application = UIApplication.shared.delegate as! AppDelegate
    managedContext = application.persistentContainer.viewContext
}


func createRoute(name: String) -> Route {
    let routeEntity = NSEntityDescription.entity(forEntityName: "Route", in: managedContext)!
    let route = NSManagedObject(entity: routeEntity, insertInto: managedContext)

    route.setValue(name, forKeyPath: "name")

    route.setValue(Date().timeIntervalSince1970, forKey: "ts")

    do {
        try managedContext.save()
    } catch let error as NSError {
        print("Could not save. \(error), \(error.userInfo)")
    }

    return route as! Route
}

func createLocation(loc: CLLocation, route: Route) {

    let locationEntity = NSEntityDescription.entity(forEntityName: "Location", in: managedContext)!
    let location = NSManagedObject(entity: locationEntity, insertInto: managedContext)

    location.setValue(loc.coordinate.latitude, forKeyPath: "latitude")
    location.setValue(loc.coordinate.longitude, forKeyPath: "longitude")
    location.setValue(loc.altitude, forKeyPath: "altitude")
    location.setValue(loc.timestamp, forKeyPath: "ts")
    location.setValue(route, forKeyPath: "route")

    do {
        try managedContext.save()
    } catch let error as NSError {
        print("Could not save. \(error), \(error.userInfo)")
    }
}

func getAllRoutes () -> [Route] {
    let routeFetch = NSFetchRequest<NSFetchRequestResult>(entityName: "Route")
    let routeResults = try! managedContext.fetch(routeFetch)
    return routeResults as! [Route]
}

func getLocationsByRoute (name: String) -> [Location] {
    let locFetch = NSFetchRequest<NSFetchRequestResult>(entityName: "Location")

    //select * from ZLOCATION, ZROUTE where ZLOCATION.ZROUTE = ZROUTE.Z_PK and ZROUTE.ZNAME = ?
    locFetch.predicate = NSPredicate(format: "locations.route = %@", name)
    locFetch.sortDescriptors = [NSSortDescriptor.init(key: "ts", ascending: false)]

    let locations = try! managedContext.fetch(locFetch)

    return locations as! [Location]
}

}

如果位置表中没有主键,如何创建查询以获取给定路线的所有位置?您可以在代码中看到我有一个getLocationsByRoute方法,但是无法使查询正常工作。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

  • 如果您有Route对象,请从locations属性中获取位置
  • 如果必须提取对象,请使用谓词格式

    locFetch.predicate = NSPredicate(format: "route.name = %@", name)
    

    密钥路径始终为<relationship name>.<attribute name> –在这种情况下,请获取所有Location的{​​{1}}与相关name相等的对象。

答案 1 :(得分:0)

停止用数据库术语思考,核心数据是一个ORM。

您可以通过访问locations类的Route属性来获得路线的所有位置,因为它对应于RouteLocation之间的一对多关系

let locations = someRoute.locations