2015-10-18 39 views
1

我warpper類CLLoaction境界過濾CLLocation

包裝

class Location: Object { 
    dynamic var long: Double = 0 
    dynamic var lat: Double = 0 
} 

我不得不篩選存儲Location對於那些在1公里半徑根據我目前的位置。我認爲NSPred block with block會完成這項工作,但是realm不支持它。所以我的問題是如何以其他方式實現它? 當然,我可以做這樣的事情:

let locations = realm.objects(Location) 
var locationsInRadius = [Location]() 
for l in locations { 
    let location = CLLocation(latitude: l.lat, longitude: l.long) 
    if (location.distanceFromLocation(currentLocation) < radius){ 
     locationsInRadius.append(l) 
    } 
} 

但是,根據過濾器整個領域的概念覺得不妥。

回答

4

不能按距離搜索對象,但可以使用邊界框進行搜索。只需添加latitudelongitude領域你的對象,那麼:

  1. 獲取當前位置
  2. 圍繞該位置創建一個邊界框
  3. 通過邊框

在代碼過濾您的對象,可以這樣:

// 0. This example uses MapKit to calculate the bounding box 
    import MapKit 

    // 1. Plenty of answers for this one... 
    let currentLocation = CLLocationCoordinate2DMake(37.7749295, -122.4194155) 

    // 2. Create the bounding box with, 1km radius 
    let region = MKCoordinateRegionMakeWithDistance(currentLocation, 1000, 1000) 
    let northWestCorner = CLLocationCoordinate2DMake(
     currentLocation.latitude + (region.span.latitudeDelta), 
     currentLocation.longitude - (region.span.longitudeDelta) 
    ) 
    let southEastCorner = CLLocationCoordinate2DMake(
     currentLocation.latitude - (region.span.latitudeDelta), 
     currentLocation.longitude + (region.span.longitudeDelta) 
    ) 

    // 3. Filter your objects 
    let predicate = NSPredicate(format: "lat BETWEEN {%f, %f} AND lon BETWEEN {%f, %f}", 
     northWestCorner.latitude, 
     southEastCorner.latitude, 
     northWestCorner.longitude, 
     southEastCorner.longitude 
    ) 

    let nearbyLocations = realm.objects(MyLocation).filter(predicate) 

請注意,您仍然可以將您的CLLocation對象存儲爲其他用途,但您不需要它進行搜索。

另請注意,由於此搜索框的內容不是您想要的,而是半徑爲1公里的圓,因此可以返回大於1公里的結果。如果這樣做不好,你需要減小半徑或製作更好的謂詞。

+0

好吧..說實話,我已經做到了你說的,但我希望有知名的NSPredicate(不是基於塊)。 :) –

+0

對不起,我不明白你的意思...這*是*使用一個衆所周知的NSPredicate進行搜索,並沒有阻止...你能解釋一下嗎?此外,這完全不同於您展示的示例......這不會像您的示例那樣加載您領域中的每個對象,只是您需要的對象。 – Donamite

+0

提前注意到[製作中的PR](https://github.com/realm/realm-cocoa/pull/2199/files),它將此功能引入綁定,但使用相同的底層方法邊界框。 – marius

2

出於某種原因,使用單個謂詞(lat BETWEEN {%f, %f} AND lon BETWEEN {%f, %f})不適用於當前版本的Realm。我用這個漂亮的lib:https://github.com/mhergon/RealmGeoQueries

這是怎樣的謂詞內建成並正常工作:https://github.com/mhergon/RealmGeoQueries/blob/master/GeoQueries.swift

let topLeftPredicate = NSPredicate(format: "%K <= %f AND %K >= %f", latitudeKey, box.topLeft.latitude, longitudeKey, box.topLeft.longitude) 
let bottomRightPredicate = NSPredicate(format: "%K >= %f AND %K <= %f", latitudeKey, box.bottomRight.latitude, longitudeKey, box.bottomRight.longitude) 
let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [topLeftPredicate, bottomRightPredicate]) 

基本上,這裏是如何使用它:

let results = try! Realm() 
    .findNearby(YourModelClass.self, origin: location.coordinate, radius: 500, sortAscending: nil) 

您也可以通過傳遞2個額外的參數(latitudeKey和longitudeKey)來更改默認的「lat」和「lng」鍵。

感謝https://github.com/mhergon提供此庫。