4

CoreData を使用するアプリに取り組んでいます。緯度と経度の値を保持する場所エンティティがあります。ユーザーの場所までの距離で並べ替えられたエンティティを取得したいと思います。ソート記述子を距離式 sqrt ((x1 - x2)^2 + (y1 - y2)^2) に設定しようとしましたが、例外 "... keypath ... not found in entity" で失敗します。

NSString *distanceFormula = [NSString stringWithFormat:@"sqrt(((latitude - %f) * (latitude - %f)) + ((longitude - %f) * (longitude - %f)))", 
                            location.coordinate.latitude, 
                            location.coordinate.latitude, 
                            location.coordinate.longitude, 
                            location.coordinate.longitude];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:distanceFormula ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
NSError *error;
NSArray *result = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];

それらをすべてフェッチしてからコードでソートするのではなく、すでにソートされたオブジェクトをフェッチしたいと思います。

ヒントをいただければ幸いです。

4

1 に答える 1

5

NSSortDescriptorクエリ文字列ではなく、オブジェクトのプロパティのキー文字列で初期化する必要があります。これは、距離式をオブジェクトのメソッドとして実装する必要があることを意味します。

その後、フェッチの前または後にソートするかどうかは問題ではありません。

NSArray *result = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
result = [result sortedArrayUsingSelector:@"compareDistance"];

別のポイント。緯度のように、距離の式が正しく機能しません。そして長い。赤道上にいない限り、同じ縮尺ではありません。これを使って:

double latDiff = lat1-lat2;
double longDiff = (long1-long2)*cos(lat1); //cos() assumes lat1 is in radians
double distance = sqrt(latDiff*latDiff+longDiff*longDiff);

距離が数百キロメートルを超える場合は、球面余弦法が必要です。

// assuming angles in radian,
double separation = acos( sin(lat1)*sin(lat2) + cos(lat1)*cos(lat2)*cos(long1-long2) );
double distance = separation*earthRadius;
于 2010-05-07T12:14:23.683 に答える