2017-02-10 1 views
0

인스턴스가 로컬 SQL-Lite 스토리지에서 유지되는 NSManagedObject 파생 클래스 (엔티티)가 있습니다. 클래스는 경도와 위도 속성도 가지고 있으므로 특정 좌표로부터의 거리를 기준으로 엔티티를 가져와야합니다. 사용자 지정 함수를 사용하여 NSPredicate 사용했지만 함수를 구현하는 방법에 대한 설명서를 찾을 수 없습니다 (... 지원하는 경우). 핵심 데이터 엔티티에서 이와 같은 동적 필터링을 수행하는 방법에 대한 아이디어가 있습니까? 나는 NSPredicate withBlock을 시도했지만, SQL-Lite 데이터베이스에서 유지되는 객체에서는 작동하지 않는다. 도와주세요.동적 위치에서 거리를 기준으로 핵심 데이터 엔티티 필터링

답변

3

코어 데이터로는이를 수행 할 수 없습니다. Transient 속성을 사용하여 동적 위치에서 거리를 모델링 한 다음 엔티티를 가져온 후 해당 Transient 속성을 기반으로 항목을 정렬 할 수 있습니다. 그러나 영구 속성 인 경우 영구 저장소에서 속성을 가져올 수만 있습니다.

실제로 좌표를 인덱싱하면 구형 창에서 쿼리하는 것이 매우 빠릅니다. 동적 위치의 위도/경도, 검색 반경을 더한/빼기, 투영되지 않은 데이터 (순수한 위도/경도, UTM 또는 유사한 그리드가 아닌 경우)의 경도 창에 대한 코사인 (위도) 조정을 던져 창을 작성하십시오.

정말 빠르지 않다면 엔티티에 geohash를 저장할 수 있습니다.이 문자열은 접두사 검색을 할 수있는 문자열을 제공합니다. 자세한 내용은 https://en.wikipedia.org/wiki/Geohash을 참조하십시오. 또는 실제 공간 인덱스를 구현할 수 있습니다. 그러나 이러한 접근 방식 중 하나를 구현할 가치가있는 핵심 데이터 성능 문제는 본 적이 없습니다.

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

아니 내가 필요 정확히 ... 텍사스 – Sergiob

관련 문제