Closed mhergon closed 8 years ago
The code as provided doesn't compile so I suspect you've edited it down from a larger example. Can you share a more complete example of what you're doing?
Here's a working test I threw together based on the code you provided:
class InfoPoint: Object {
dynamic var id = ""
dynamic var name: String = ""
dynamic var location: LocationProperty?
}
class LocationProperty: Object {
dynamic var lat: Double = 0.0
dynamic var lng: Double = 0.0
}
let realm = Realm()
try! realm.write {
realm.create(InfoPoint.self, value: ["LKPRT", "Lakeport, CA", [39.0431, -122.9158]])
realm.create(InfoPoint.self, value: ["CHCH", "Christchurch, New Zealand", [-43.5300, 172.6203]])
}
var results = realm.objects(InfoPoint).filter("location.lat > %f AND location.lng < %f", 39, 120)
print("Found \(results.count) results")
print("The first result's ID is \(results.first!.id)")
results = realm.objects(InfoPoint).filter("location.lat < %f AND location.lng > %f", 0, 0);
print("Found \(results.count) results")
print("The first result's ID is \(results.first!.id)")
@bdash I've updated the query code and I tried setting manually "location.lat" key and works fine. Only fails if I pass keys as variable like example
@bdash After see your code, I'm tried this workaround:
let topLeftPredicate = NSPredicate(format: "\(latitudeKey) <= %f AND \(longitudeKey) >= %f", box.topLeft.latitude, box.topLeft.longitude)
let bottomRightPredicate = NSPredicate(format: "\(latitudeKey) >= %f AND \(longitudeKey) <= %f", box.bottomRight.latitude, box.bottomRight.longitude)
and works fine!
Thanks!
In your example you're calling Results.filter(predicate)
, but that won't compile since filter
is an instance method rather than a class method. How are you really invoking filter
?
Also, what are the values of latitudeKey
and longitudeKey
?
The change from %K
to Swift string interpolation wouldn't fix the error you're hitting. I suspect you changed something else at the same time that really fixed the issue. That said, I'd suggest sticking to NSPredicate's interpolation syntax for this since it'll correctly handle the case where the keys you're substituting are keywords or operators.
@bdash You can view my original code at this file: https://github.com/mhergon/RealmGeoQueries/blob/0aa53e46d81899357cf23fdf4f363d3361f03935/GeoQueries.swift
Query:
Realm().findNearby(Marina.self, origin: coordinate, radius: distance, sortAscending: true, latitudeKey: "location.lat", longitudeKey: "location.lng", distanceKey: "dist")
And I only changed to string interpolation, I promise ;)
The exception you were seeing was:
*\ Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<RLMAccessor_v0_Marina 0x7fcf3967f270> valueForUndefinedKey:]: this class is not key value coding-compliant for the key location.lat.'
This exception is being thrown by key-value coding machinery, typically called via -valueWithKeyPath:
. Results.filter
doesn't use KVC in its implementation so the exception cannot have come from calling Results.filter
. That's why I think something else is going on.
@bdash Yes, after some tests, keeps failing. Have you any workaround?
I'm still not able to reproduce the problem you're seeing. I went so far as to download your project from GitHub, build and run the example, modify it to contain a second model class with a link to the example's Point
class, and update the query to specify longitudeKey
and latitudeKey
as you describe. No sign of the exception you mentioned.
Can you share a self-contained example that reproduces the problem? If that's not possible then can you provide more information about what the code you're using looks like? What do your model classes look like, for instance? The snippet you mentioned contains a reference to a Marina
class that you've not shared the definition for.
From looking at GeoQueries.swift I see the following:
let location = CLLocation(latitude: obj.valueForKey(latitudeKey) as! CLLocationDegrees, longitude: obj.valueForKey(longitudeKey) as! CLLocationDegrees)
That looks like the culprit. valueForKey
doesn't traverse key paths, so it tries to access "location.lat" as a property of obj
. valueForKeyPath
traverses key paths so it'll load the location
property from obj
, then use valueForKey
to retrieve the lat
property from it.
@bdash The first exception occurs at "filterGeoBox:" method. So, above code has not executed...
I attached an example code with exception. Thanks! Subproperty Fails.zip
Thanks for the reproducible test case. When running the application I see an exception like so:
2015-12-15 12:44:53.672 Subproperty Fails[10245:440394] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<RLMAccessor_v0_Marina 0x7ff3ac805bd0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key location.lat.'
*** First throw call stack:
(
0 CoreFoundation 0x0000000101501e65 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x0000000103241deb objc_exception_throw + 48
2 CoreFoundation 0x0000000101501aa9 -[NSException raise] + 9
3 Foundation 0x000000010195d888 -[NSObject(NSKeyValueCoding) valueForUndefinedKey:] + 226
4 Realm 0x0000000100e15ae0 -[RLMObjectBase valueForUndefinedKey:] + 352
5 Foundation 0x00000001018b3997 -[NSObject(NSKeyValueCoding) valueForKey:] + 280
6 Realm 0x0000000100e1592d -[RLMObjectBase valueForKey:] + 237
7 GeoQueries 0x0000000100dab121 _TFFeRdq_C10RealmSwift6Object_10GeoQueriesCS_7Results15filterGeoRadiusuRdq_S0__FGS2_q__FTVSC22CLLocationCoordinate2D6radiusSd13sortAscendingGSqSb_11latitudeKeySS12longitudeKeySS11distanceKeySS_GSaq__U_FS0_Sb + 305
8 GeoQueries 0x0000000100daa9f7 _TPA__TFFeRdq_C10RealmSwift6Object_10GeoQueriesCS_7Results15filterGeoRadiusuRdq_S0__FGS2_q__FTVSC22CLLocationCoordinate2D6radiusSd13sortAscendingGSqSb_11latitudeKeySS12longitudeKeySS11distanceKeySS_GSaq__U_FS0_Sb + 263
9 GeoQueries 0x0000000100dab747 _TTRGRdq_C10RealmSwift6Object_XFo_oq__dSbzoPSs9ErrorType__XFo_iq__dSbzoPS1___ + 39
10 libswiftCore.dylib 0x000000010367f8c4 _TFeRq_Ss12SequenceType_SsS_6filteruRq_S__fq_FzFzqqq_S_9GeneratorSs13GeneratorType7ElementSbGSaqqq_S_9GeneratorS0_7Element_ + 468
11 GeoQueries 0x0000000100da9a6a _TFeRdq_C10RealmSwift6Object_10GeoQueriesCS_7Results15filterGeoRadiusuRdq_S0__fGS2_q__FTVSC22CLLocationCoordinate2D6radiusSd13sortAscendingGSqSb_11latitudeKeySS12longitudeKeySS11distanceKeySS_GSaq__ + 1162
12 GeoQueries 0x0000000100da9590 _TFE10GeoQueriesC10RealmSwift5Realm10findNearbyuRdq_CS0_6Object_fS1_FTMq_6originVSC22CLLocationCoordinate2D6radiusSd13sortAscendingGSqSb_11latitudeKeySS12longitudeKeySS11distanceKeySS_GSaq__ + 688
13 Subproperty Fails 0x0000000100c58ca5 _TFFC17Subproperty_Fails18MainViewController11viewDidLoadFS0_FT_T_U_FGSqCSo7NSError_T_ + 709
14 Subproperty Fails 0x0000000100c58de7 _TTRXFo_oGSqCSo7NSError__dT__XFo_iT5errorGSqS____iT__ + 23
15 Subproperty Fails 0x0000000100c57b31 _TPA__TTRXFo_oGSqCSo7NSError__dT__XFo_iT5errorGSqS____iT__ + 81
16 Subproperty Fails 0x0000000100c592ff _TFFC17Subproperty_Fails18MainViewController7marinasFS0_FGSqFT5errorGSqCSo7NSError__T__T_U_FTCSo20NSURLSessionDataTaskGSqPSs9AnyObject___T_ + 879
17 Subproperty Fails 0x0000000100c5cf43 _TTRXFo_oCSo20NSURLSessionDataTaskoGSqPSs9AnyObject___dT__XFo_iTS_GSqPS0_____iT__ + 35
18 Subproperty Fails 0x0000000100c5c161 _TPA__TTRXFo_oCSo20NSURLSessionDataTaskoGSqPSs9AnyObject___dT__XFo_iTS_GSqPS0_____iT__ + 81
19 Subproperty Fails 0x0000000100c5cf77 _TTRXFo_iTCSo20NSURLSessionDataTaskGSqPSs9AnyObject____iT__XFo_oS_oGSqPS0____dT__ + 39
20 Subproperty Fails 0x0000000100c5cfcd _TTRXFo_oCSo20NSURLSessionDataTaskoGSqPSs9AnyObject___dT__XFdCb_dS_dGSqPS0____dT__ + 77
21 AFNetworking 0x0000000100d1b021 __116-[AFHTTPSessionManager dataTaskWithHTTPMethod:URLString:parameters:uploadProgress:downloadProgress:success:failure:]_block_invoke97 + 241
22 AFNetworking 0x0000000100d3e1db __72-[AFURLSessionManagerTaskDelegate URLSession:task:didCompleteWithError:]_block_invoke_2151 + 203
23 libdispatch.dylib 0x0000000104782e5d _dispatch_call_block_and_release + 12
24 libdispatch.dylib 0x00000001047a349b _dispatch_client_callout + 8
25 libdispatch.dylib 0x000000010478b2af _dispatch_main_queue_callback_4CF + 1738
26 CoreFoundation 0x0000000101461d09 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
27 CoreFoundation 0x00000001014232c9 __CFRunLoopRun + 2073
28 CoreFoundation 0x0000000101422828 CFRunLoopRunSpecific + 488
29 GraphicsServices 0x0000000106a6bad2 GSEventRunModal + 161
30 UIKit 0x0000000101d1e610 UIApplicationMain + 171
31 Subproperty Fails 0x0000000100c5fb0d main + 109
32 libdyld.dylib 0x00000001047d792d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Walking up the backtrace to find the caller of valueForKey
we see:
_TFFeRdq_C10RealmSwift6Object_10GeoQueriesCS_7Results15filterGeoRadiusuRdq_S0__FGS2_q__FTVSC22CLLocationCoordinate2D6radiusSd13sortAscendingGSqSb_11latitudeKeySS12longitudeKeySS11distanceKeySS_GSaq__U_FS0_Sb
Demangling that name gives:
ext.GeoQueries.RealmSwift.Results<A where A: RealmSwift.Object>.(filterGeoRadius <A where A: RealmSwift.Object> (RealmSwift.Results<A>) -> (__C.CLLocationCoordinate2D, radius : Swift.Double, sortAscending : Swift.Bool?, latitudeKey : Swift.String, longitudeKey : Swift.String, distanceKey : Swift.String) -> [A]).(closure #1)
So the exception is coming from within filterGeoRadius
. Changing the two calls to valueForKey
to valueForKeyPath
within filterGeoRadius
gets me past this exception. It blows up slightly later due to trying to store to a dist
property that doesn't appear to exist on any of the model classes. Tweaking the call to findNearby
to drop the distanceKey
parameter gets around that issue.
It works! Thank you @bdash
Hi,
I'm getting an error when I trying to make a NSPredicate with subproperty;
and
When I execute this query:
I'm getting this error:
I tried with block version of NSPredicate but Realm doesn't support it. Any idea? Thanks!