具有功能参数的CoreData谓词

时间:2019-04-02 04:36:21

标签: ios swift core-data nspredicate cllocation

我正在尝试在谓词定义中包含一个函数。这可能吗?

假设您有一个地方信息的核心数据实体,其属性为 纬度和经度。

我想在地图视图中添加注释 距用户位置的指定距离。当然,我可以遍历整个数据库并计算每个地方与 用户位置,但我将有35000个位置,看来 在谓词中有一个谓词会更有效 fetchedResultsController设置。

  

我尝试了以下代码,但收到一条错误消息“问题与   userInfo为(null)的子谓词BLOCKPREDICATE(0x2808237b0)“

isdir()

在fetchedResultsController内部:

func myDistanceFilter(myLat : CLLocationDegrees, myLong : CLLocationDegrees, cdLat : CLLocationDegrees, cdLong : CLLocationDegrees) -> Bool {

    let myLocation = CLLocation(latitude: myLat, longitude: myLong)
    let cdLocation = CLLocation(latitude: cdLat, longitude: cdLong)

    if myLocation.distance(from: cdLocation) < 5000.0 {
        return true
    } else {
        return false
    }
}//myDistancePredicate

如果在谓词中可能有一个块/函数,那么如何获得对要评估的实体对象的属性的引用?

任何指导将不胜感激。

2 个答案:

答案 0 :(得分:2)

对其他遇到类似问题的人的补充观察。

至少在我看来,考虑到上面的pbasdf和Jerry的建议,没有理由要一个区域是圆形的。我将命名一个几乎为矩形的区域。我用纬度和经度值进行了一些测试。这些纬度和经度值可以缩放为包含用户指定的圆半径的矩形。一度的纬度约为69英里,而芝加哥纬度的一度约为51英里。我使用了以下内容:

var myUserLatitude : CLLocationDegrees!
var myUserLongitude : CLLocationDegrees!

在视图的初始化文件中:

guard let userLatitude = locationManager.location?.coordinate.latitude else {return}
guard let userLongitude = locationManager.location?.coordinate.longitude else {return}
myUserLatitude = userLatitude
myUserLongitude = userLongitude

在创建的fetchedResultsController变量中:

let latitudeMinPredicate = NSPredicate(format: "latitude >= %lf", myUserLatitude - 1.0)
let latitudeMaxPredicate = NSPredicate(format: "latitude <= %lf", myUserLatitude + 1.0)
let longitudeMinPredicate = NSPredicate(format: "longitude >= %lf", myUserLongitude - 1.0)
let longitudeMaxPredicate = NSPredicate(format: "longitude <= %lf", myUserLongitude + 1.0)

var compoundPredicate = NSCompoundPredicate()
compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [anotherUnrelatedPredicate,latitudeMinPredicate,latitudeMaxPredicate,longitudeMinPredicate, longitudeMaxPredicate])
fetchRequest.predicate = compoundPredicate        

很显然,我将创建另一个属性来按用户所需区域缩放1.0值。最初的测试似乎可以正常工作,而且我不敢相信测试有多快。从字面上看,tableView会在viewController搜索到封闭的mapView时填充。

答案 1 :(得分:1)

是的,这是可能的。 NSPredicate确实有+predicateWithBlock:init(block:)

但是,如果您向下滚动该页面,则会看到坏消息:

Core Data在内存和原子存储中支持基于块的谓词,但在基于SQLite的存储中不支持。

因此,无论您使用内存中存储还是代码过滤,无论哪种方式,您都需要将这35,000个项目带入内存,而蛮力方法的性能会很差。

在某种程度上讲,不再适合使用SQL –使用 real 代码可以获得更好的性能。我认为您的要求远远超出了这一点。这将是一个有趣的优化计算机科学项目。您需要进行一些预计算,类似于向数据库添加 index 。考虑将region属性添加到place实体中,然后编写谓词以获取目标位置区域内的所有位置以及所有直接邻居。然后过滤掉代码中的候选对象。我确定这是由其他人完成的-考虑到手机网络中的小区-但Core Data不会免费为您提供此