Start a new topic

Update to Xcode 5 and KinveyKit 1.26.3

Hi all,



So I am trying to update to the newest KinveyKit because of some user creation issues on the old sdk. While updating I started getting some crashes on some function calls that before where not have issues. So far there are two errors, which keep in mind work fine on the old sdk.



The first error is CRASH: objectId is `nil'. I am not sure what this is I thought it was a functino I am calling but after looking at hte stack trace it is being called on a Data store that I did not create. I have no idea what might be the cause of this issue. Stack trace is below:



2014-02-26 11:53:53.958 Soulodex[3187:6007] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'objectId is `nil`.'

*** First throw call stack:

(

0 CoreFoundation 0x02d1e5e4 __exceptionPreprocess + 180

1 libobjc.A.dylib 0x0290d8b6 objc_exception_throw + 44

2 CoreFoundation 0x02dae6a1 -[NSException raise] + 17

3 Soulodex libc++abi.dylib: 0x0013e4d1 -[KCSBackgroundAppdataStore loadObjectWithID:withCompletionBlock:withProgressBlock:cachePolicy:] + 145

4 Soulodex 0x0013e9d8 -[KCSBackgroundAppdataStore loadObjectWithID:withCompletionBlock:withProgressBlock:] + 120

5 Soulodex 0x00125cc2 __74-[KCSAppdataStore loadObjectWithID:withCompletionBlock:withProgressBlock:]_block_invoke + 178

6 Soulodex 0x001255ba -[DataStoreOperation start] + 58

7 Foundation 0x025e4af4 __NSOQSchedule_f + 62

8 libdispatch.dylib 0x038ce4b0 _dispatch_client_callout + 14

9 libdispatch.dylib 0x038bb018 _dispatch_async_redirect_invoke + 202

10 libdispatch.dylib 0x038ce4b0 _dispatch_client_callout + 14

11 libdispatch.dylib 0x038bceeb _dispatch_root_queue_drain + 287

12 libdispatch.dylib 0x038bd137 _dispatch_worker_thread2 + 39

13 libsystem_pthread.dylib 0x03c5adab _pthread_wqthread + 336

14 libsystem_pthread.dylib 0x03c5ecce start_wqthread + 30

)

terminating with uncaught exception of type NSExceptionlibc++abi.dylib:

terminating with uncaught exception of type NSException



This next paragraph is what I was thinking it was but after further looking and testing I am thinking I am wrong. I will leave this in here though for reference.



So I am guessing this is from the loadObjectWithID function that I am calling. Right now I have an array of object id's that I am passing this function and it goes and gets all the objects with those ids. Before it was working fine and getting all the objects correctly. Now though it is saying objetid is nil, and I am not sure if this partisans to the field objectId on the object I am getting out is nil or if it is talking about the array that I am passing it has nil values in it?? My guess is the former and this is why: I have a check to see if the array is nil so that is not it, but also I am not aware of any nil values in the array I am passing it. The code I was thinking is messing up is below but I am just not sure:











The second error I am getting is CRASH: Can't do regex matching on object. The context is I am using a regex to search on an array of strings. So I am creating a query that is geocoding and searching on a array of strings. This was the way it worked on the old SDK I am not sure what has changed and how I need to change it to get the same result on the new SDK. Code is below:



-(void) callToDatabaseOnPlaceCollectionUsingCurrentLocationWithSkip: (int) skip

withSkipLimit: (int) skipLimit

withChannelQueryName: (NSString *) channelName

withDelegate: (id) delegate {

//pointer to a query

KCSQuery *geoQuery = nil, *mutiQuery = nil, *channelQuery = nil;



KCSAppdataStore *placesStore = [KCSAppdataStore storeWithOptions:@{ KCSStoreKeyCollectionName : placesCollection,

KCSStoreKeyCollectionTemplateClass : [Place class]}];



geoQuery = [KCSQuery queryOnField:KCSEntityKeyGeolocation

usingConditional:kKCSNearSphere

forValue:@[@(currentLocation.coordinate.longitude), @(currentLocation.coordinate.latitude)]];



if (channelName != nil) {

//setup the compound query

channelQuery = [KCSQuery queryOnField:@"channels" withRegex:channelName];

mutiQuery = [[KCSQuery alloc] init];

[mutiQuery addQuery:geoQuery];

[mutiQuery addQuery:channelQuery];

}



//set the skip amount, and limit amount

(mutiQuery == nil ? geoQuery : mutiQuery).limitModifer = [[KCSQueryLimitModifier alloc] initWithLimit:skipLimit];

(mutiQuery == nil ? geoQuery : mutiQuery).skipModifier = [[KCSQuerySkipModifier alloc] initWithcount:skip];



//send the request to the database.

[placesStore queryWithQuery:mutiQuery == nil ? geoQuery : mutiQuery

withCompletionBlock:^(NSArray *objectsOrNil, NSError *errorOrNil){

if ([delegate respondsToSelector:@selector(databaseCallDidFinishWithObjects:withErrors:isUpdate:)]) {

[delegate databaseCallDidFinishWithObjects:objectsOrNil withErrors:errorOrNil isUpdate: skip == 0 ? true : false];

}

} withProgressBlock:^(NSArray *objects, double percentComplete) {

//NSLog(@"progress = %f", percentComplete);

}];

}



Here is stack trace:



2014-02-26 12:14:58.894 Soulodex[430:370f] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Can't do regex matching on object (

"Pensacola African-American Enterprise Directory",

"African-American Owned Businesses"

).'

*** First throw call stack:

(

0 CoreFoundation 0x02d1e5e4 __exceptionPreprocess + 180

1 libobjc.A.dylib 0x0290d8b6 objc_exception_throw + 44

2 Foundation 0x0264bc40 -[NSMatchingPredicateOperator performPrimitiveOperationUsingObject:andObject:] + 519

3 Foundation 0x0259219e -[NSPredicateOperator performOperationUsingObject:andObject:] + 306

4 Foundation 0x02591f2c -[NSComparisonPredicate evaluateWithObject:substitutionVariables:] + 347

5 Foundation 0x02591dc9 -[NSPredicate evaluateWithObject:] + 48

6 Foundation 0x02591d49 _filterObjectsUsingPredicate + 418

7 Foundation 0x02591b02 -[NSArray(NSPredicateSupport) filteredArrayUsingPredicate:] + 328

8 Soulodex 0x00164bad -[KCSObjectCache pullQuery:route:collection:] + 477

9 Soulodex 0x0013fc7d -[KCSBackgroundAppdataStore queryWithQuery:withCompletionBlock:withProgressBlock:cachePolicy:] + 285

10 Soulodex 0x001400c8 -[KCSBackgroundAppdataStore queryWithQuery:withCompletionBlock:withProgressBlock:] + 120

11 Soulodex 0x00126222 __72-[KCSAppdataStore queryWithQuery:withCompletionBlock:withProgressBlock:]_block_invoke + 178

12 Soulodex 0x0012554a -[DataStoreOperation start] + 58

13 Foundation 0x025e4af4 __NSOQSchedule_f + 62

14 libdispatch.dylib 0x038ce4b0 _dispatch_client_callout + 14

15 libdispatch.dylib 0x038bb018 _dispatch_async_redirect_invoke + 202

16 libdispatch.dylib 0x038ce4b0 _dispatch_client_callout + 14

17 libdispatch.dylib 0x038bceeb _dispatch_root_queue_drain + 287

18 libdispatch.dylib 0x038bd137 _dispatch_worker_thread2 + 39

19 libsystem_pthread.dylib 0x03c5adab _pthread_wqthread + 336

20 libsystem_pthread.dylib 0x03c5ecce start_wqthread + 30

)

libc++abi.dylib: terminating with uncaught exception of type NSException





Also the last thing as a passing comment: The create user function for older SDK's is broken. I am not sure if this was intentional but figured I would let you all know. When you create a user it creates the user fine but it does not log in the user.

Since there a few issues here:



1. The value passed to loadObjectWithID: is nil at the time of evaluation, which is on a background thread. How are you calling this function?



2. The regex crash: this is a bug, and will be fixed in the next update.



3. Older sdk user create issue: thanks for letting us know. We'll look in to it.
below is the loadObjectWIthID function call in my code:



-(void) callToDatabaseOnCollection: (NSString *) collectionName withObjectIds: (NSMutableArray *) objectIds WithDelegate:(id) delegate {

// make a call to the database and grab all the channels.

KCSAppdataStore *store = [KCSAppdataStore storeWithOptions:@{

KCSStoreKeyCollectionName : collectionName,

KCSStoreKeyCollectionTemplateClass : [self createClassFromCollection:collectionName]}];



[store loadObjectWithID:objectIds withCompletionBlock:^(NSArray *objectsOrNil, NSError *errorOrNil){

if ([delegate respondsToSelector:@selector(databaseCallOnCollectionFinishWithObjects:withErrors:)]) {

[delegate databaseCallOnCollectionFinishWithObjects:objectsOrNil withErrors:errorOrNil];

}

} withProgressBlock:^(NSArray *objects, double percentComplete) {

//NSLog(@"progress = %f", percentComplete);

}];

}



And at first I thought it was that as well but i added in some tests to check for nil values, and nothing was nil. But then at closer look at the stack trace you can see that it called loadObjectWithID 3 times before failing so not sure what to make of it. Could it be a weak pointer thing?? I was thinking it should not be because I make sure I have strong pointers to those objects. Also that would be weird that it would stop working when I update to the newest kinveykit. If you think it will help I can get the exact version of the KinveyKit I am using in this.



Thanks for any Help!

Sean
What do you mean by a "weak pointer thing"? As you can see from the stack trace that value of "objectId" is passed through to a NSOperation and evaluated sometime later on a different thread, so if there is no reference back to the objectIds this will be nil. I'm also going to do the parameter assert earlier in this case in the next version of the lib just to check that it's not nil coming in to the top call.
Haha sorry should have been more specific.



So what I mean by the weak pointer thing is this: if there is not a strong pointer to the object when it is passed to the other functions on another thread/in another class and the original class does not need it anymore it has a chance of being de-allocated. I have had this happen with arrays and/or objects being passed between screens. SO I tend to use strong pointers when ever I can now though. But this seems like one of those issues. Because like I said when I passed in the array it was not nil. The array had object id's in it.



The error is 'objectId is nil.' which suggests it is not my array but a field on a object is nil which makes no since because kinvey sdk handles all that. The name of my array is "objectIds" not "objectId". Now in all of my objects the "_id" field is called "objectId" that is why I am seeing it this way. If this was the case then it would suggest we have an object in the database without a "_id" field. Am I way off base here or are you seeing the discrepancy as well?
The array is probably not nil at the time `queryWithQuery` is called, but since that value is not used until later inside a nsoperation on a background queue, it is being cleaned up in between. I'd look at where the array is first generated and the conditions under which that value is removed.
Ya I will look into it some more. It is just weird that the same code is working before the update. I will post back just in case anyone else has this issue.
Login or Signup to post a comment