I am having trouble fetching information from Firebase RemoteConfig. On app install, I have a language selection screen before the MainController view controller. On the MainController View controller, I am doing a RemoteConfig fetch. It works the first time, when the language selection screen is shown before the MainController view controller. But, from the next time, it crashes on this particular line:
[self.remoteConfig fetchWithExpirationDuration:expirationDuration completionHandler:^(FIRRemoteConfigFetchStatus status, NSError *error) {
With the following exception:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSTaggedPointerString firstObject]: unrecognized selector sent to instance 0xa0000000000616a2'
*** First throw call stack:
(
0 CoreFoundation 0x000000010d20134b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x000000010cc6221e objc_exception_throw + 48
2 CoreFoundation 0x000000010d270f34 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
3 CoreFoundation 0x000000010d186c15 ___forwarding___ + 1013
4 CoreFoundation 0x000000010d186798 _CF_forwarding_prep_0 + 120
5 English 0x0000000107f44e1b -[GIPLocale googleLanguageWithAppleLanguages:] + 33
6 English 0x0000000107f45396 -[GIPLocale recalculateLocale] + 54
7 English 0x0000000107f44c26 -[GIPLocale initWithLanguageMappings:] + 99
8 English 0x0000000107f44b77 __25+[GIPLocale googleLocale]_block_invoke + 41
9 libdispatch.dylib 0x000000010da900cd _dispatch_client_callout + 8
10 libdispatch.dylib 0x000000010da751fc dispatch_once_f + 501
11 English 0x0000000107f44b4c +[GIPLocale googleLocale] + 42
12 English 0x0000000107f42d06 +[RCNDevice deviceLocale] + 31
13 English 0x0000000107f43344 +[RCNDevice hasDeviceContextChanged:projectIdentifier:] + 325
14 English 0x0000000107f3e133 -[RCNConfigFetch fetchAllConfigsWithExpirationDuration:completionHandler:] + 150
15 English 0x0000000107f3577f -[FIRRemoteConfig fetchWithExpirationDuration:completionHandler:] + 77
UPDATE: It doesn't matter if I show the language selection screen or not. It always works on a fresh install and stops working from next launches.
This is my full code I am using.
-(void)viewDidAppear:(BOOL)animated{
//Display select language settings
if (![[NSUserDefaults standardUserDefaults] boolForKey:DISPLAY_LANGUAGE_SETTING])
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:TRUE forKey:DISPLAY_LANGUAGE_SETTING];
[defaults synchronize];
//Display Language Screen
AGSelectLanguageViewController *languageViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"AGSelectLanguageViewController"];
self.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:languageViewController animated:NO completion:nil];
}
[self configFireBase];
}
-(void)configFireBase{
// Firebase Configuration
self.remoteConfig = [FIRRemoteConfig remoteConfig];
//Enabling development mode
FIRRemoteConfigSettings *remoteConfigSettings = [[FIRRemoteConfigSettings alloc] initWithDeveloperModeEnabled:YES];
self.remoteConfig.configSettings = remoteConfigSettings;
//Set default Remote Config values
[self.remoteConfig setDefaultsFromPlistFileName:#"RemoteConfigDefaults"];
[self fetchConfig];
}
- (void)fetchConfig {
_discount_percentage = self.remoteConfig[DISCOUNT_PERCENTAGE].numberValue.floatValue;
long expirationDuration = 3600;
if (self.remoteConfig.configSettings.isDeveloperModeEnabled) {
expirationDuration = 0;
}
[self.remoteConfig fetchWithExpirationDuration:expirationDuration completionHandler:^(FIRRemoteConfigFetchStatus status, NSError *error) {
if (status == FIRRemoteConfigFetchStatusSuccess) {
NSLog(#"Config fetched!");
[self.remoteConfig activateFetched];
} else {
NSLog(#"Config not fetched");
NSLog(#"Error %#", error.localizedDescription);
}
}];
}
Where am I wrong? Please help.
The GIPLocale class does some mapping between Google and Apple names for locales, and as part of that it pulls the app's locales from NSUserDefaults:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSArray *languages = [defaults objectForKey:#"AppleLanguages"];
I am guessing that somewhere that defaults entry is getting set to just a string or similar rather than an array - check if you're referencing that string anywhere in your app.
Related
While testing Voip Pushes i came across this error
2016-10-19 14:03:26.809 linphone[332:33741] Can't endBackgroundTask: no background task exists with identifier c6, or it may have already been ended. Break in UIApplicationEndBackgroundTaskError() to debug.
Oct 19 14:03:26 linphone[332] <Notice>: ios/(honeAppDelegate.m:492 ) PushKit received with payload : <PKPushPayload: 0x14ee5b30>
Oct 19 14:03:26 linphone[332] <Notice>: ios/(honeAppDelegate.m:494 ) incoming voip notfication: {
aps = {
alert = Testando;
};
}
2016-10-19 14:03:26.818 linphone[332:33741] -[__NSCFString objectForKey:]: unrecognized selector sent to instance 0x18e5c760
2016-10-19 14:03:26.821 linphone[332:33741] Crash: -[__NSCFString objectForKey:]: unrecognized selector sent to instance 0x18e5c760
2016-10-19 14:03:26.902 linphone[332:33741] Stack Trace: (
0 CoreFoundation 0x24bff933 <redacted> + 150
1 libobjc.A.dylib 0x2439ae17 objc_exception_throw + 38
2 CoreFoundation 0x24c052b5 <redacted> + 0
3 CoreFoundation 0x24c02ee1 <redacted> + 700
4 CoreFoundation 0x24b2e238 _CF_forwarding_prep_0 + 24
5 linphone 0x0002ee2f -[LinphoneAppDelegate processRemoteNotification:] + 214
6 linphone 0x00030f15 __78-[LinphoneAppDelegate pushRegistry:didReceiveIncomingPushWithPayload:forType:]_block_invoke_2 + 96
7 libdispatch.dylib 0x012ddb7f _dispatch_call_block_and_release + 10
8 libdispatch.dylib 0x012ddb6b _dispatch_client_callout + 22
9 libdispatch.dylib 0x012e2655 _dispatch_main_queue_callback_4CF + 1680
10 CoreFoundation 0x24bc1b6d <redacted> + 8
11 CoreFoundation 0x24bc0067 <redacted> + 1574
12 CoreFoundation 0x24b0f229 CFRunLoopRunSpecific + 520
13 CoreFoundation 0x24b0f015 CFRunLoopRunInMode + 108
14 GraphicsServices 0x260ffac9 GSEventRunModal + 160
15 UIKit 0x291e3189 UIApplicationMain + 144
16 linphone 0x0002b949 main + 124
17 libdyld.dylib 0x247b7873 <redacted> + 2
)
2016-10-19 14:03:26.907 linphone[332:33741] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString objectForKey:]: unrecognized selector sent to instance 0x18e5c760'
*** First throw call stack:
(0x24bff91b 0x2439ae17 0x24c052b5 0x24c02ee1 0x24b2e238 0x2ee2f 0x30f15 0x12ddb7f 0x12ddb6b 0x12e2655 0x24bc1b6d 0x24bc0067 0x24b0f229 0x24b0f015 0x260ffac9 0x291e3189 0x2b949 0x247b7873)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
Here is the code XCode points me to when the app crashes.
- (void)processRemoteNotification:(NSDictionary *)userInfo {
NSDictionary *aps = [userInfo objectForKey:#"aps"];
if (aps != nil) {
NSDictionary *alert = [aps objectForKey:#"alert"];
if (alert != nil) {
NSString *loc_key = [alert objectForKey:#"loc-key"];
/* if we receive a remote notification, it is probably because our TCP background socket was no more working.
As a result, break it and refresh registers in order to make sure to receive incoming INVITE or MESSAGE*/
if (linphone_core_get_calls(LC) == NULL) { // if there are calls, obviously our TCP socket shall be working
//linphone_core_set_network_reachable(LC, FALSE);
if (!linphone_core_is_network_reachable(LC)) {
LinphoneManager.instance.connectivity = none; //Force connectivity to be discovered again
[LinphoneManager.instance setupNetworkReachabilityCallback];
}
if (loc_key != nil) {
NSString *callId = [userInfo objectForKey:#"call-id"];
if (callId != nil) {
[LinphoneManager.instance addPushCallId:callId];
} else {
LOGE(#"PushNotification: does not have call-id yet, fix it !");
}
if ([loc_key isEqualToString:#"IC_MSG"]) {
[self fixRing];
}
}
}
}
}
LOGI(#"Notification %# processed", userInfo.description);
}
As you can see, I do receive the push notification but only on the log, it wont pop on my phone and the app crashes.
You are accessing the value for key "loc-key" in "alert" dictionary and in the payload "alert" dictionary doesn't have the value for this key, therefore it is crashing at NSString *loc_key = [alert objectForKey:#"loc-key"];
I ran into the same issue. The server side was pushing notifications containing only the "Incoming Notification" string. Thus, the objectForKey:#"loc-key" would crash - The push notification did not contain strings in the expected format. To work around this, I checked the contents of the push notifications from the server. For legacy push servers, a comparison of alert to "Incoming Notification" would yield true. In this case, I would then set alert to nil to bypass the crash.
NSDictionary *alert = [aps objectForKey:#"alert"];
BOOL result = [alert isEqual:#"Incoming Notification"];
if (result == true)
{
if (linphone_core_get_calls(LC) == NULL) { // if there are calls, obviously our TCP socket shall be working
if (!linphone_core_is_network_reachable(LC)) {
LinphoneManager.instance.connectivity = none; //Force connectivity to be discovered again
[LinphoneManager.instance setupNetworkReachabilityCallback];
}
}
alert = nil;
}
if (alert != nil) {
...
}
While validating for null values ,the crashes with
-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object
When I am using all mutable type.(crashing only in iOS 9,other versions of my app in Appstore are working fine)
Can anyone suggest me how to handle this at null condition to setValue for key.
NSMutableArray *tempelementsArray=[[NSMutableArray alloc]init];
if(![[catDic objectForKey:#"menuElementList"] isEqual:#""]){
tempelementsArray = [catDic objectForKey:#"menuElementList"];
if(tempelementsArray != nil && [tempelementsArray count]>0)
{
for (NSInteger j=0; j<tempelementsArray.count; j++) {
NSMutableDictionary *elementDic = [[NSMutableDictionary alloc]init];
elementDic = [tempelementsArray objectAtIndex:j];
[elementDic enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
if ([obj isKindOfClass:[NSNull class]])
{
[elementDic setValue:#"" forKey:key];//App crashes here when one of the value is NULL
}
} ];
}
with below crash:
*** Terminating app due to uncaught exception NSInternalInconsistencyException', reason: '-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'
*** First throw call stack:
(
0 CoreFoundation 0x00df3a94 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x0051be02 objc_exception_throw + 50
2 CoreFoundation 0x00df39bd +[NSException raise:format:] + 141
3 CoreFoundation 0x00d0ed68 -[__NSCFDictionary setObject:forKey:] + 104
4 Foundation 0x001051ba -[NSMutableDictionary(NSKeyValueCoding) setValue:forKey:] + 68
5 coreDataMenuSample 0x000481d9 __33-[ViewController SaveToCoredata:]_block_invoke188 + 217
6 CoreFoundation 0x00df2849 ____NSDictionaryEnumerate_block_invoke417 + 41
7 CoreFoundation 0x00cd5452 CFBasicHashApply + 130
8 CoreFoundation 0x00d12481 __NSDictionaryEnumerate + 273
9 CoreFoundation 0x00d122ed -[NSDictionary enumerateKeysAndObjectsWithOptions:usingBlock:] + 45
10 CoreFoundation 0x00d12235 -[NSDictionary enumerateKeysAndObjectsUsingBlock:] + 53
11 coreDataMenuSample 0x00043e71 -[ViewController SaveToCoredata:] + 6481
12 coreDataMenuSample 0x0004239d -[ViewController viewDidLoad] + 893
13 UIKit 0x0133fd74 -[UIViewController _sendViewDidLoadWithAppearanceProxyObjectTaggingEnabled] + 44
14 UIKit 0x013448c2 -[UIViewController loadViewIfRequired] + 1556
)
libc++abi.dylib: terminating with uncaught exception of type NSException
I have even checked this similar issue Strange “mutating method sent to immutable object” error when adding an object to a mutable array
Saving CLLocation error: Mutating method sent to immutable object
Look at your code, I think the problem is this line
NSMutableDictionary *elementDic = [[NSMutableDictionary alloc]init];
elementDic = [tempelementsArray objectAtIndex:j];
tempelementsArray contains an instance of NSDictionary instead of NSMutableDictionary. Change to this code will help:
NSMutableDictionary *elementDic = [[NSMutableDictionary alloc]initWithDictionary:tempelementsArray[j]];
There are several things wrong with your code :
First it's not because you initialise a variable with a mutable object that subsequent initialisations will be converted to mutable objects. So when you do :
NSMutableDictionary *elementDic = [[NSMutableDictionary alloc]init];
elementDic = [tempelementsArray objectAtIndex:j];
elementDic contains whatever was in the array at index j, so in this case probably an immutable object. You have to make mutable copies of your objects if you want them mutable.
Second, you can't mutate a dictionary while you enumerate it (which is what you are trying to do here). You have to make a mutable copy and mutate the copy while you enumerate the original.
Third, if you expect [catDic objectForKey:#"menuElementList"] to be an array, why do you test if it's equal to an empty string ?!
Here is a fixed version of your code (with modern obj-C syntax which is much easier to read by the way)
NSDictionary *catDic = ...
NSArray *tempElementsArray = catDic[#"menuElementList"];
NSMutableArray *mutableTempElementsArray = [NSMutableArray arrayWithCapacity:tempElementsArray.count];
if (![tempElementsArray isEqual:#""] && tempElementsArray != nil && tempElementsArray.count > 0)
{
for (NSUInteger j = 0; j < tempElementsArray.count; j++)
{
NSDictionary *elementsDic = tempElementsArray[j];
NSMutableDictionary *mutableElementsDic = [NSMutableDictionary dictionaryWithCapacity:elementsDic.count];
[elementsDic enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
if (obj == [NSNull null]) {
obj = #"";
}
mutableElementsDic[key] = obj;
}];
[mutableTempElementsArray addObject:mutableElementsDic];
}
}
NSMutableDictionary *mutableCatDic = [NSMutableDictionary dictionaryWithDictionary:catDic];
mutableCatDic[#"menuElementList"] = mutableTempElementsArray;
I have recorded a crash of my app, but the last line in my app (5 Control) points just to the method begin. How do I know in which line the problem is?
0 CoreFoundation 0x185f0af50 __exceptionPreprocess + 132
1 libobjc.A.dylib 0x1924141fc objc_exception_throw + 60
2 CoreFoundation 0x185f0fc04 -[NSObject(NSObject) doesNotRecognizeSelector:] + 220
3 CoreFoundation 0x185f0d930 ___forwarding___ + 912
4 CoreFoundation 0x185e2d5dc _CF_forwarding_prep_0 + 92
5 Control 0x10005acb4 -[PaymillPaymentService handleTransactionListRequest:] (PaymillPaymentService.m:211)
6 Foundation 0x186a7416c __103+[__NSOperationInternal _observeValueForKeyPath:ofObject:changeKind:oldValue:newValue:indexes:context:]_block_invoke96 + 28
7 libdispatch.dylib 0x1929ec014 _dispatch_call_block_and_release + 24
8 libdispatch.dylib 0x1929ebfd4 _dispatch_client_callout + 16
9 libdispatch.dylib 0x1929f32b8 _dispatch_root_queue_drain + 556
10 libdispatch.dylib 0x1929f34fc _dispatch_worker_thread2 + 76
11 libsystem_pthread.dylib 0x192b816bc _pthread_wqthread + 356
12 libsystem_pthread.dylib 0x192b8154c start_wqthread + 4
Here the [lengthy] method code. I see a couple of places where I can add the check but how to I know it for sure that I fixed the issue? The problem is sporadical and I cannot reproduce it easily.
- (void)handleTransactionListRequest:(ServiceRequest *)serviceRequest
{
LRURLRequestOperation* operation = serviceRequest.operation;
NSHTTPURLResponse *response = (NSHTTPURLResponse *)operation.URLResponse;
if (response.statusCode == 200)
{
if (operation.responseData)
{
NSError *parserError = nil;
NSDictionary *data = [NSJSONSerialization JSONObjectWithData:operation.responseData options:0 error:&parserError];
//NSLog(#"%#", data);
if (!parserError)
{
NSArray* transactions = [data objectForKey:#"data"];
if (0 == serviceRequest.currentOffset)
{
NSNumber* totalCountObj = [data objectForKey:#"data_count"];
serviceRequest.totalCount = [totalCountObj intValue];
}
int loadedCount = 0;
if (transactions)
{
for (id object in transactions)
{
TransactionInfo* info = [self createTransactionFrom:object];
[serviceRequest.transactionList addTransaction:info];
[info release];
loadedCount++;
}
}
if (loadedCount + serviceRequest.currentOffset >= serviceRequest.totalCount)
{
if ([serviceRequest.delegate respondsToSelector:#selector(transactionListLoadingComplete:)])
[serviceRequest.delegate transactionListLoadingComplete:serviceRequest];
serviceRequest.transactionList.timeStamp = [[NSDate date] timeIntervalSince1970];
NSLog(#"COMPLETE: %d transaction loaded ", serviceRequest.totalCount);
}
else
{
serviceRequest.currentOffset += loadedCount;
bool needToContinue = YES;
if ([serviceRequest.delegate respondsToSelector:#selector(transactionListLoadingContinue:)])
needToContinue = [serviceRequest.delegate transactionListLoadingContinue];
if (needToContinue)
{
[self continueRetrievingTransactionListFor:serviceRequest];
NSLog(#"CONTINUE: %d of %d loaded ", serviceRequest.currentOffset, serviceRequest.totalCount);
}
}
return; // all OK cases
}
}
}
if ([serviceRequest.delegate respondsToSelector:#selector(transactionListLoadingFailed:with:)])
[serviceRequest.delegate transactionListLoadingFailed:serviceRequest with:response.statusCode];
NSLog(#"ERROR: Loading Transactions Response Code: %ld", (long)response.statusCode);
}
Short Answer:
You are sending a message to an object that cannot validly respond to it. The stack trace is telling you that when you make the call [PaymillPaymentService handleTransactionListRequest:] that PaymillPaymentService cannot accept handleTransactionListRequest.
Long answer:
Look at the stack trace here:
5 Control 0x10005acb4 -[PaymillPaymentService handleTransactionListRequest:] (PaymillPaymentService.m:211)
This is telling you that in the file PaymillPaymentService.m on line 211 you are sending PaymillPaymentService the message handleTransactionListRequest to which it cannot validly respond. In your discussion with rmaddy, Hot Licks, and Paulc11 you mentioned that line 211 is the function entry for handleTransactionListRequest (in whatever file it resides). If that's the case it is coincidental.
If you want further follow up you need to post PaymillPaymentService.m and ensure that you include all the line numbers.
For some reason, I randomly sometimes get this crash.
Fatal Exception: NSInternalInconsistencyException
Cannot determine hasNextPage: paginator is not loaded.
Thread : Fatal Exception: NSInternalInconsistencyException
0 CoreFoundation 0x309a1f4b __exceptionPreprocess + 130
1 libobjc.A.dylib 0x3b1386af objc_exception_throw + 38
2 CoreFoundation 0x309a1e25 +[NSException raise:format:]
3 Foundation 0x31349fe3 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 90
4 Poka 0x004f0f71 -[RKPaginator hasNextPage] (RKPaginator.m:151)
5 Poka 0x00289a41 __66-[PokaLocationContentManagerSingleton fetchLatestPlantsWithCount:]_block_invoke (PokaLocationContentManagerSingleton.m:345)
6 Poka 0x004f2495 __24-[RKPaginator loadPage:]_block_invoke157 (RKPaginator.m:231)
7 Poka 0x004e9355 __66-[RKObjectRequestOperation setCompletionBlockWithSuccess:failure:]_block_invoke244 (RKObjectRequestOperation.m:477)
8 libdispatch.dylib 0x3b61bd1b _dispatch_call_block_and_release + 10
9 libdispatch.dylib 0x3b61bd07 _dispatch_client_callout + 22
10 libdispatch.dylib 0x3b62278d _dispatch_main_queue_callback_4CF$VARIANT$mp + 268
11 CoreFoundation 0x3096c819 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 8
12 CoreFoundation 0x3096b0ed __CFRunLoopRun + 1300
13 CoreFoundation 0x308d5c27 CFRunLoopRunSpecific + 522
14 CoreFoundation 0x308d5a0b CFRunLoopRunInMode + 106
15 GraphicsServices 0x355c9283 GSEventRunModal + 138
16 UIKit 0x33179049 UIApplicationMain + 1136
17 Poka 0x0006df95 main (main.m:17)
18 libdyld.dylib 0x3b640ab7 start + 2
I am loading the Paginator like this:
- (void)fetchLatestPlantsWithCount:(NSNumber *)count
{
RKObjectManager *objectManager = [RKObjectManager sharedManager];
NSString *requestString = [NSString stringWithFormat:#"/api/rest/plants/?count=%#&limit=:perPage&offset=:offset", count];
NSDictionary *parameters = nil;
if(_dateFilterLastModifiedAppend)
parameters = [[NSDictionary alloc]initWithObjectsAndKeys:_dateFilterLastModifiedAppend, #"last_modified_date__gte", nil];
RKPaginator *paginator = [objectManager paginatorWithPathPattern:requestString parameters:parameters];
paginator.perPage = API_PER_PAGE_LIMIT;
[ZAActivityBar showWithStatus:[NSString stringWithFormat:NSLocalizedStringFromTable(#"Downloading latest plants: %# remaining", #"PokaLocalizable", nil), count]];
[paginator setCompletionBlockWithSuccess:^(RKPaginator *paginator, NSArray *objects, NSUInteger page) {
if([paginator hasNextPage])
{
[ZAActivityBar showWithStatus:[NSString stringWithFormat:NSLocalizedStringFromTable(#"Downloading latest plants: %# remaining", #"PokaLocalizable", nil), [NSNumber numberWithInt:([count integerValue] - paginator.offset)]]];
[paginator loadNextPage];
}
else
{
[self fetchLatestProductionLinesCount];
}
} failure:^(RKPaginator *paginator, NSError *error) {
[self fetchLatestProductionLinesCount];
}];
[paginator loadPage:1];
}
Finally, I added some code to RestKit in order to load the paginator. I don't think it is the problem though.
- (RKPaginator *)paginatorWithPathPattern:(NSString *)pathPattern parameters:(NSDictionary *)parameters
{
NSAssert(self.paginationMapping, #"Cannot instantiate a paginator when `paginationMapping` is nil.");
NSMutableURLRequest *request = [self requestWithMethod:#"GET" path:pathPattern parameters:parameters];
RKPaginator *paginator = [[RKPaginator alloc] initWithRequest:request paginationMapping:self.paginationMapping responseDescriptors:self.responseDescriptors];
#ifdef _COREDATADEFINES_H
paginator.managedObjectContext = self.managedObjectStore.mainQueueManagedObjectContext;
paginator.managedObjectCache = self.managedObjectStore.managedObjectCache;
paginator.fetchRequestBlocks = self.fetchRequestBlocks;
#endif
paginator.operationQueue = self.operationQueue;
Class HTTPOperationClass = [self requestOperationClassForRequest:request fromRegisteredClasses:self.registeredHTTPRequestOperationClasses];
if (HTTPOperationClass) [paginator setHTTPOperationClass:HTTPOperationClass];
return paginator;
}
The only difference is that I pass some parameters to it.
The thing I don't understand is that I load other objects, WITH that same code with the only difference being the type of objects I am downloading. I execute almost that same code right before executing this one, and it works perfectly fine. Hence, my question as to I am confused...
Some more information:
It says the object count is 1, that page is 1, but apparently it is not loaded?
Note that I call the paginator multiple times within the same page. I do the paginator for one type of objects... once it is done I do it for another one... and so on.
All pull requests that I mentioned before were merged already to master. So just use the newest version.
I found an issue and fixed it if you are interested. I posted Pull Request on RestKit github page
https://github.com/RestKit/RestKit/pull/2156
I would recommend to use my fork on branch inventorum where I also cherry picked malloc error fix:
https://github.com/bimusiek/RestKit/commits/inventorum
I'm curious to know why I'm receiving an exception on this code and as to what this exception means. When I remove the for loop, as indicated below, it works fine. When I include it, I get an exception.
-(void) loadVenues {
NSString *latLon = #"34.0500, -118.2500"; // approximate latLon of The Mothership (a.k.a Apple headquarters)
NSString *clientID = kCLIENTID;
NSString *clientSecret = kCLIENTSECRET;
//34.0500° N, 118.2500
NSDictionary *queryParams = #{#"ll" : latLon,
#"client_id" : clientID,
#"client_secret" : clientSecret,
#"categoryId" : #"4bf58dd8d48988d1e0931735",
#"v" : #"20140118"};
[[RKObjectManager sharedManager] getObjectsAtPath:#"/v2/venues/search"
parameters:queryParams
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
_venues = mappingResult.array;
NSMutableArray *temp = [(NSArray*)_venues mutableCopy];
for (int i =0; i < _venues.count; i++)
{
NSUInteger index = 0;
for (int j = 0; j <_venues.count; j++)
{
//((MyObjectType *) [myArray objectAtIndex:0]).intProperty = 12345;
if(((Venue *) [temp objectAtIndex:index]).location.distance > 0)
{
Venue *holder= [temp objectAtIndex:index];
[temp removeObjectAtIndex:index];
NSUInteger indexer = index +1;
[temp addObject:[temp objectAtIndex:indexer]];
//replace a with a+1
[temp replaceObjectAtIndex:indexer withObject:holder];
//[temp addObject:holder atIndex: index+1];
//a[i+1]=holder;
index++;
}
else {index++;}
}
}
_venues = temp;
[self.tableView reloadData];
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"What do you mean by 'there is no coffee?': %#", error);
}
];
}
I'm getting an exception at this line:
[temp addObject:[temp objectAtIndex:indexer]];
And I'm not sure why.
Here is the error:
2014-07-02 21:43:12.536 CoffeeKit[63581:60b] I restkit:RKLog.m:33 RestKit logging initialized...
2014-07-02 21:43:12.655 CoffeeKit[63581:60b] I restkit.network:RKObjectRequestOperation.m:150 GET 'https://api.foursquare.com/v2/venues/search?categoryId=4bf58dd8d48988d1e0931735&client_id=ZE5VJOPEO1PP3NDFVCM3O2ZUXWDDJRB20XDDGH3OETBKOVZB&client_secret=5LGY2CEASBQZQS5P0LYFICWDKMDOHJJ00F3G24LT4J4DX4X3&ll=34.0500%2C%20-118.2500&v=20140118'
2014-07-02 21:43:13.085 CoffeeKit[63581:f03] I restkit.network:RKObjectRequestOperation.m:220 GET 'https://api.foursquare.com/v2/venues/search?categoryId=4bf58dd8d48988d1e0931735&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&ll=34.0500%2C%20-118.2500&v=20140118' (200 OK / 30 objects) [request=0.4171s mapping=0.0128s total=0.4486s]
2014-07-02 21:43:13.087 CoffeeKit[63581:60b] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 29 beyond bounds [0 .. 28]'
*** First throw call stack:
(
0 CoreFoundation 0x00000001023a0495 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x00000001020ff99e objc_exception_throw + 43
2 CoreFoundation 0x0000000102346745 -[__NSArrayM objectAtIndex:] + 213
3 CoffeeKit 0x0000000100002efa __34-[MasterViewController loadVenues]_block_invoke + 602
4 CoffeeKit 0x000000010009310b __66-[RKObjectRequestOperation setCompletionBlockWithSuccess:failure:]_block_invoke244 + 91
5 libdispatch.dylib 0x0000000102c9a851 _dispatch_call_block_and_release + 12
6 libdispatch.dylib 0x0000000102cad72d _dispatch_client_callout + 8
7 libdispatch.dylib 0x0000000102c9d3fc _dispatch_main_queue_callback_4CF + 354
8 CoreFoundation 0x00000001023fe289 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
9 CoreFoundation 0x000000010234b854 __CFRunLoopRun + 1764
10 CoreFoundation 0x000000010234ad83 CFRunLoopRunSpecific + 467
11 GraphicsServices 0x00000001033e2f04 GSEventRunModal + 161
12 UIKit 0x0000000100cace33 UIApplicationMain + 1010
13 CoffeeKit 0x0000000100003733 main + 115
14 libdyld.dylib 0x0000000102efe5fd start + 1
15 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
As you can see from your stack, your error is occurring because you attempt to access the object at index 29, which is outside of the array's bounds:
* -[__NSArrayM objectAtIndex:]: index 29 beyond bounds [0 .. 28]
In your case, it's probably arising from this line:
NSUInteger indexer = index +1;
[temp addObject:[temp objectAtIndex:indexer]];
Which I'm assuming you're using to get the value of the next object. Once the array reaches the 28th object, however, you attempt to access the imaginary 29th object.
Bottom line: refactor your code so that you only access objects that exist.
You are getting out of bounds by accessing the NEXT element in the array, 2 things. you can directly use 'j' to access the element (instead of index, so u dont have to increment it urself) and you can change your for from
for (int j = 0; j <_venues.count; j++)
to
for (int j = 0; j <_venues.count-1; j++)
By the way if all you need is sorting, NSMutableArray offers many options:
Rearranging Content
– exchangeObjectAtIndex:withObjectAtIndex:
– sortUsingDescriptors:
– sortUsingComparator:
– sortWithOptions:usingComparator:
– sortUsingFunction:context:
– sortUsingSelector: