2017-02-10 7 views
0

NSManagedObject派生クラス(エンティティ)がインスタンスをローカルSQL-Liteストレージに保持しています。クラスには経度と緯度のプロパティもあり、特定の座標からの距離に基づいてエンティティを取得する必要があります。私はカスタム関数でNSPredicateを使用しようとしましたが、私は関数を実装する方法に関する文書を見つけることができませんでした(もしそれがサポートされていれば)。コアデータエンティティでこの種の動的フィルタリングを実行する方法について誰もが知っていますか?私はNSPredicate withBlockを試してみましたが、SQL-Liteデータベースで永続化されたオブジェクトでは動作しません。助けてください。動的な位置からの距離によるコアデータエンティティのフィルタリング

答えて

3

コアデータを使って行うことはできません。 Transientプロパティを使用して、エンティティがフェッチされた後の動的な場所からの距離をモデル化し、そのTransientプロパティに基づいてアイテムを並べ替えることもできます。ただし、永続ストアである場合は、永続ストアからプロパティを取得することしかできません。

実際には、座標がインデックス付けされている場合、長方形のウィンドウ内の点をクエリするのは非常に高速です。投影されていないデータ(純粋な緯度/経度、UTMなどのグリッドではない)の場合は、動的位置の緯度/経度、検索半径のプラス/マイナスを経て経度ウィンドウの余弦(緯度)調整を投げてウィンドウを構築します。

これで十分ではない場合は、エンティティにジオハッシュを保存して、プレフィックス検索を行うことができる文字列を提供することができます。説明はhttps://en.wikipedia.org/wiki/Geohashを参照してください。あるいは、真の空間インデックスを実装することもできます。しかし、私はこれらのアプローチのどちらかを実装する価値があるCore Dataパフォーマンスの問題を経験したことはありません。

0

私は緯度/経度座標として自分の位置をデータモデルに保存します。次に、緯度/経度座標の半直角の領域を見つけてそれを照会するヘルパー拡張を書きました。これにより結果セットが大幅に制限されるため、場所別にソートする必要がある場合は、CLLocation距離計算機を使用して結果のオブジェクトをソートすることができます。

私はCLCircularRegionを作成し、クエリを作成する私のbuildPredicate()関数を見ることができます。ここで

は、私が使用しているコードです:

スウィフト3

extension CLLocationDegrees { 
     static var north: CLLocationDegrees { 
      return 90.0 
     } 
     static var south: CLLocationDegrees { 
      return -90.0 
     } 
     static var east: CLLocationDegrees { 
      return 180.0 
     } 
     static var west: CLLocationDegrees { 
      return -180.0 
     } 

     var radians: Double { 
      return Double.pi * self/180.0 
     } 
    } 

    extension CLLocationCoordinate2D { 
     var metersPerDegreeLatitude: CLLocationDistance { 
      return 111319.4907932736 
     } 
     var metersPerDegreeLongitude: CLLocationDistance { 
      return max(0.0, cos(self.latitude.radians) * self.metersPerDegreeLatitude) 
     } 
    } 

    extension CLCircularRegion { 
     var northernmostLatitude: CLLocationDegrees { 
      let longitude = self.center.latitude + self.radius/self.center.metersPerDegreeLatitude 
      return min(longitude, .north) 
     } 

     var southernmostLatitude: CLLocationDegrees { 
      let longitude = self.center.latitude - self.radius/self.center.metersPerDegreeLatitude 
      return max(longitude, .south) 
     } 

     var easternmostLongitude: CLLocationDegrees { 
      guard self.northernmostLatitude <= .north else { 
       return .east 
      } 
      guard self.southernmostLatitude >= .south else { 
       return .east 
      } 
      return min(.east, self.center.longitude + self.radius/(self.center.metersPerDegreeLongitude + 0.0001)) 
     } 

     var westernmostLongitude: CLLocationDegrees { 
      guard self.northernmostLatitude <= .north else { 
       return .west 
      } 
      guard self.southernmostLatitude >= .south else { 
       return .west 
      } 
      return max(.west, self.center.longitude - self.radius/(self.center.metersPerDegreeLongitude + 0.0001)) 
     } 

     func buildPredicate(latitudeName: String = "latitude", longitudeName: String = "longitude") -> NSPredicate { 
      let args = [self.southernmostLatitude, self.northernmostLatitude, self.westernmostLongitude, self.easternmostLongitude] 
      return NSPredicate(format: "\(latitudeName) >= %@ && \(latitudeName) <= %@ && \(longitudeName) >= %@ && \(longitudeName) <= %@", argumentArray: args) 
     } 
    } 
+0

ありません私が必要まさに... TX – Sergiob

関連する問題