CoreData:获取具有特殊条件的实体

时间:2014-04-13 02:25:57

标签: ios core-data nspredicate

在我的数据库中,我有一个名为“Address”的实体,有140k行地址。每个地址都有“lat”和“lng”属性,表示地址的纬度和经度。

如果我从位置服务获取了用户位置,我如何遍历所有地址并找到离用户位置最近的地址?

如果我可以获得地址的纬度和经度,我已经有了构建Haversine距离的代码,但我的问题是我不知道如何在谓词中做到这一点。

我目前从数组中获取最近地址的代码:

// user location acquired from location service
CLLocationCoordinate2D currentLocationCoordinate = location.coordinate;
float dist = FLT_MAX;
int nearestAddressIndex = -1;
for(int i = 0; i < [addresses count]; ++i) {
    NSDictionary *address = addresses[i];
    Haversine *haverObject = [[Haversine alloc] initWithLat1:currentLocationCoordinate.latitude
                                                        lon1:currentLocationCoordinate.longitude
                                                        lat2:[address[@"lat"] floatValue]
                                                        lon2:[address[@"lng"] floatValue]];
    if ([haverObject toMeters] < dist ) {
        dist = [haverObject toMeters];
        nearestAddressIndex = i;
    }
}

有没有办法构建谓词?或者我必须获取数组中的所有地址并遍历数组吗?

我有点不愿意做后者,因为我担心它可能导致应用因内存压力而终止。

在我的应用中其他地方发生的另一个类似问题:

在第二种情况下,我需要获取位于用户位置周围某个半径范围内的所有地址。下面是我的数组代码:

CLLocationCoordinate2D currentLocationCoordinate = location.coordinate;
CGFloat threshold = 500.0f;
NSMutableArray *nearbyStation = [NSMutableArray array];

for (NSDictionary *station in [DataHelper sharedInstance].stations)
{
    CGFloat lat = [station[@"lat"] floatValue];
    CGFloat lng = [station[@"lng"] floatValue];

    Haversine *haverObject = [[Haversine alloc] initWithLat1:currentLocationCoordinate.latitude
                                                        lon1:currentLocationCoordinate.longitude
                                                        lat2:lat
                                                        lon2:lng];
    if ([haverObject toMeters] <= threshold)
    {
        [nearbyStation addObject:station];
    }
}

我有上面存储在数组中的数据代码。但是,我怎么能对存储在核心数据中的“地址”做同样的事情呢?

3 个答案:

答案 0 :(得分:0)

如果只遍历实体的一个值,那就更好了。你可以尝试改编这样的东西:

NSEntityDescription *description = [NSEntityDescription entityForName:@"Address"
                                               inManagedObjectContext:[yourContext managedObjectContext]];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:description];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"exampleLatitute < dist"];
[request setPredicate:predicate];
NSError *error = nil;
NSArray *array = [[yourContext managedObjectContext] executeFetchRequest:request
                                                                   error:&error];

答案 1 :(得分:0)

您的谓词需要搜索用户位置的lat lng范围内的项目。

Check this link以获取如何构造谓词的示例。一旦你拥有了所有关闭的项目,你就可以对它们进行排序以确定距离。该链接还提供了如何执行此操作的示例。

答案 2 :(得分:0)

您可以创建谓词以查找地址的子集 在给定范围内,即在用户位置附近。 例如:(minLat < lat < maxLat) AND (minLon < lon < maxLon)。 NSPredicate无法处理更复杂的方程式。

predicate = [NSPredicate predicateWithFormat:@"lng > %@ AND lng < %@ AND lat > %@ AND lat < %@", minLong, maxLong, minLat, maxLat];

[request setPredicate:predicate];
NSError *error;
NSArray *matchingData = [context executeFetchRequest:request error:&error];