I have an issue I cant solve. Im creating an iOS application with Core Data framework. Everything was going just fine until I got NSRangeException. This exception I get in function which checks if Application data needs to be updated.
My code is:
- (BOOL) isTimetableUpdatedWithJSONData:(NSMutableDictionary*) data
{
appDelegate = [[UIApplication sharedApplication] delegate];
managedObjectContext = [appDelegate managedObjectContext];
//Do database update check logic here
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"MobileTimetableDataHash" inManagedObjectContext:managedObjectContext]];
NSError *error = nil;
NSArray *results = [managedObjectContext executeFetchRequest:request error:&error];
if (error != nil)
{
[self printErrorAlert];
}
//THERE IS ERROR HERE
NSManagedObject* changesGrabbed = [results objectAtIndex:0];
NSString *changesFromDatabase = [changesGrabbed valueForKey:#"changes"];
NSString *changesFromService = [data valueForKeyPath:#"changes"];
if ([changesFromService isEqualToString:changesFromDatabase])
{
return YES;
}
else
{
[changesGrabbed setValue:changesFromService forKey:#"changes"];
[managedObjectContext save:&error];
if (error != nil)
{
[self printErrorAlert];
}
return NO;
}
}
Exception:
2014-06-12 21:36:12.034 MIF[437:60b] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 0 beyond bounds for empty array'
*** First throw call stack:
(
0 CoreFoundation 0x0000000101cb3495 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x0000000101a1299e objc_exception_throw + 43
2 CoreFoundation 0x0000000101c6be3f -[__NSArrayI objectAtIndex:] + 175
3 MIF 0x0000000100001942 -[MIFTimetableService isTimetableUpdatedWithJSONData:] + 514
4 MIF 0x000000010000219d -[MIFAppDelegate synchrinizeTimetableService] + 157
5 MIF 0x0000000100001dc2 -[MIFAppDelegate application:didFinishLaunchingWithOptions:] + 114
6 UIKit 0x00000001005ba3d9 -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 264
7 UIKit 0x00000001005babe1 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1605
8 UIKit 0x00000001005bea0c -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 660
9 UIKit 0x00000001005cfd4c -[UIApplication handleEvent:withNewEvent:] + 3189
10 UIKit 0x00000001005d0216 -[UIApplication sendEvent:] + 79
11 UIKit 0x00000001005c0086 _UIApplicationHandleEvent + 578
12 GraphicsServices 0x0000000103ce671a _PurpleEventCallback + 762
13 GraphicsServices 0x0000000103ce61e1 PurpleEventCallback + 35
14 CoreFoundation 0x0000000101c35679 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 41
15 CoreFoundation 0x0000000101c3544e __CFRunLoopDoSource1 + 478
16 CoreFoundation 0x0000000101c5e903 __CFRunLoopRun + 1939
17 CoreFoundation 0x0000000101c5dd83 CFRunLoopRunSpecific + 467
18 UIKit 0x00000001005be2e1 -[UIApplication _run] + 609
19 UIKit 0x00000001005bfe33 UIApplicationMain + 1010
20 MIF 0x0000000100001d23 main + 115
21 libdyld.dylib 0x000000010234b5fd start + 1
22 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
Guys, can anyone help me please? I realy need your help. Thank you.
Your troublemaker seems to be
NSManagedObject* changesGrabbed = [results objectAtIndex:0];
If results is an empty array, calling objectAtIndex:0 will cause a NSRangeException, because there is no object at index 0. You better call [results firstObject], which won't crash with an error if results is empty array. firstObject() just returns nil in this case.
You are attempting to retrieve an object from an empty array. You should first check to see if the array contains any objects. Use the count property:
if (results.count > 0) {
NSManagedObject* changesGrabbed = [results objectAtIndex:0];
//continue...
} else {
//Array is empty, object 0 will be beyond bounds
}
Just before
NSManagedObject* changesGrabbed = [results objectAtIndex:0];
Add a branch based on the returned results. Something like the following:
if (results && [results count] > 0) {
NSManagedObject* changesGrabbed = [results objectAtIndex:0];
...
}
Your array is empty. The stacktrace pretty much spells it out for you --
reason: '* -[__NSArrayI objectAtIndex:]: index 0 beyond bounds for
empty array'
Related
I have two modes - Mode 1 and Mode 2 which can be switched by a central button. Switch between modes allows user to see two different types of clustered annotations.
I can switch from Mode 1 to Mode 2 easily, but when I switch back to Mode 1 I'm getting this nasty error
-[__NSCFDictionary componentsSeparatedByString:]: unrecognized selector sent to instance 0x7fb1308cca50
I'm opening my code and in the TBClusteredAnnotations.m (script I'm using for clusterization). I have the following snippet of code relating to componentsSeparatedByString:
TBQuadTreeNodeData TBDataFromLine(NSString *line)
{
NSString *separator=#">>>>>>>>";
NSArray *components = [line componentsSeparatedByString: separator];
double latitude = [components[0] doubleValue];
double longitude = [components[1] doubleValue];
TBUserInfo* userInfo = malloc(sizeof(TBUserInfo));
NSString *userName = [components[2] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
userInfo->userId = malloc(sizeof(char) * userName.length + 1);
strncpy(userInfo->userId, [userName UTF8String], userName.length + 1);
NSString *userId = [components [3] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
userInfo->userImage = malloc(sizeof(char) * userId.length + 1);
strncpy(userInfo->userImage, [userId UTF8String], userId.length + 1);
return TBQuadTreeNodeDataMake(latitude, longitude, userInfo);
}
but I'm loading my annotations with the following code in the MainViewController:
-(void)annotationsmode1:(NSMutableArray*)marr
{
if(marr.count>0)
{
NSMutableArray *newMarr1=[NSMutableArray new];
NSString *separatestuff=#">>>>>>>>";
for(NSMutableDictionary *dic in marr)
{
NSString *newStr=[NSString stringWithFormat:#"%#%#",[dic[#"latitude"] isEqualToString:#""]?#" ":dic[#"latitude"],separatestuff];
newStr=[NSString stringWithFormat:#"%#%#%#",newStr,[dic[#"longitude"] isEqualToString:#""]?#" ":dic[#"longitude"],separatestuff];
newStr=[NSString stringWithFormat:#"%#%#%#",newStr,[dic[#"id"] isEqualToString:#""]?#" ":dic[#"id"],separatestuff];
newStr=[NSString stringWithFormat:#"%#%#",newStr,[dic[#"image"] isEqualToString:#""]?#" ":dic[#"image"]];
[newMarr1 addObject:newStr];
}
//NSLog(#"NEW Array: %#",newMarr);
[self.coordinateQuadTree buildTree:newMarr1];
}
}
-(void)annotationsmode2:(NSMutableArray*)marr
{
if(marr.count>0)
{
NSMutableArray *newMarr=[NSMutableArray new];
NSString *separatestuff2=#">>>>>>>>";
for(NSMutableDictionary *dic in marr)
{
NSString *newStr=[NSString stringWithFormat:#"%#%#",[dic[#"lat"] isEqualToString:#""]?#" ":dic[#"lat"],separatestuff2];
newStr=[NSString stringWithFormat:#"%#%#%#",newStr,[dic[#"lang"] isEqualToString:#""]?#" ":dic[#"lang"],separatestuff2];
newStr=[NSString stringWithFormat:#"%#%#%#",newStr,[dic[#"id"] isEqualToString:#""]?#" ":dic[#"id"],separatestuff2];
newStr=[NSString stringWithFormat:#"%#%#",newStr,[dic[#"image"] isEqualToString:#""]?#" ":dic[#"image"]];
[newMarr addObject:newStr];
}
//NSLog(#"NEW Array: %#",newMarr);
[self.coordinateQuadTree buildTree:newMarr];
}
}
UPDATE: This is the block of code where the TBDataFromLine is used
- (void)buildTree:(NSMutableArray *)lines
{
#autoreleasepool {
NSInteger count = lines.count - 1;
TBQuadTreeNodeData *dataArray = malloc(sizeof(TBQuadTreeNodeData) * count);
for (NSInteger i = 0; i < count; i++) {
dataArray[i] = TBDataFromLine(lines[i]);
}
//TBBoundingBox world = TBBoundingBoxMake(19, -166, 72, -53);
TBBoundingBox world = TBBoundingBoxMake(0,0,100,100);
_root = TBQuadTreeBuildWithData(dataArray, count, world, 4);
}
}
I've been working on this issue for hours now and still have no clue.
UPDATE: Here is the debugger's log I'm getting
2015-06-20 19:40:23.759 MapProject[13426:395344] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary componentsSeparatedByString:]: unrecognized selector sent to instance 0x7fdf93775680'
*** First throw call stack:
(
0 CoreFoundation 0x0000000112699c65 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x00000001121c3bb7 objc_exception_throw + 45
2 CoreFoundation 0x00000001126a10ad -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x00000001125f713c ___forwarding___ + 988
4 CoreFoundation 0x00000001125f6cd8 _CF_forwarding_prep_0 + 120
5 MapProject 0x000000010f469ac4 TBDataFromLine + 84
6 MapProject 0x000000010f46a36f -[TBCoordinateQuadTree buildTree:] + 191
7 MapProject 0x000000010f3d2503 -[MMViewController findSpot:] + 771
8 UIKit 0x0000000110a52da2 -[UIApplication sendAction:to:from:forEvent:] + 75
9 UIKit 0x0000000110b6454a -[UIControl _sendActionsForEvents:withEvent:] + 467
10 UIKit 0x0000000110b63919 -[UIControl touchesEnded:withEvent:] + 522
11 UIKit 0x0000000110a9f998 -[UIWindow _sendTouchesForEvent:] + 735
12 UIKit 0x0000000110aa02c2 -[UIWindow sendEvent:] + 682
13 UIKit 0x0000000110a66581 -[UIApplication sendEvent:] + 246
14 UIKit 0x0000000110a73d1c _UIApplicationHandleEventFromQueueEvent + 18265
15 UIKit 0x0000000110a4e5dc _UIApplicationHandleEventQueue + 2066
16 CoreFoundation 0x00000001125cd431 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
17 CoreFoundation 0x00000001125c32fd __CFRunLoopDoSources0 + 269
18 CoreFoundation 0x00000001125c2934 __CFRunLoopRun + 868
19 CoreFoundation 0x00000001125c2366 CFRunLoopRunSpecific + 470
20 GraphicsServices 0x000000011444da3e GSEventRunModal + 161
21 UIKit 0x0000000110a51900 UIApplicationMain + 1282
22 MapProject 0x000000010f474c2f main + 111
23 libdyld.dy
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Add an Exception break point and it will take to exactly to that line where that crash is happening. Also check 'line' cause it is changed to dictionary but you code expect it
to be a string
There is no [] operator on NSArray or NSMutableArray.
You need this:
for (NSInteger i = 0; i < count; i++) {
dataArray[i] = TBDataFromLine([lines objectAtIndex:i]);
}
Using [] on NSArray* effectively acted like "lines" was really a pointer to an array of NSMutableArray instances, whereas you wanted to get one of the items out of the array to which it pointed.
I'm getting an Exception while using removeObjectAtIndex.
I've searched in this forum but I haven't found the correct solution for this Exception. Actually, I'm getting the data from server when I click on button, I'm getting success and also I need to delete that row but the selected row is not deleting.
My Exception:- Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[NSCFArray removeObjectAtIndex:]: mutating method sent to immutable object'
*** First throw call stack:
(
0 CoreFoundation 0x000000010cfd1c65 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010c46bbb7 objc_exception_throw + 45
2 CoreFoundation 0x000000010cfd1b9d +[NSException raise:format:] + 205
3 CoreFoundation 0x000000010cfca70e -[__NSCFArray removeObjectAtIndex:] + 94
4 SkigitApplication 0x00000001097fab80 __20-[HomePage Confirm:]_block_invoke + 272
5 SkigitApplication 0x00000001098c8628 __64-[AFHTTPRequestOperation setCompletionBlockWithSuccess:failure:]_block_invoke46 + 40
6 libdispatch.dylib 0x000000011160f186 _dispatch_call_block_and_release + 12
7 libdispatch.dylib 0x000000011162e614 _dispatch_client_callout + 8
8 libdispatch.dylib 0x0000000111616a1c _dispatch_main_queue_callback_4CF + 1664
9 CoreFoundation 0x000000010cf391f9 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE + 9
10 CoreFoundation 0x000000010cefadcb __CFRunLoopRun + 2043
11 CoreFoundation 0x000000010cefa366 CFRunLoopRunSpecific + 470
12 GraphicsServices 0x000000010db6da3e GSEventRunModal + 161
13 UIKit 0x000000010acf7900 UIApplicationMain + 1282
14 SkigitApplication 0x00000001098c65bf main + 111
15 libdyld.dylib 0x0000000111663145 start + 1
16 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Here is my code: request is my array
In .h
NSMutableArray *request;
In .m
-(void)Confirm:(id)sender
{
NSString *test = [NSString stringWithFormat:#"WebserviceUrl"];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:test parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"JSON: %#", responseObject);
if([[responseObject valueForKey:#"Success"]integerValue])
{
request=[[responseObject valueForKey:#"info"]mutableCopy];
NSLog(#"array=%#",request);
frndcount=[[[request valueForKey:#"is_new"]objectAtIndex:0]mutableCopy];
NSLog(#"frndcount=%#",frndcount);
notification_id= [[[request valueForKey:#"notification_id"]objectAtIndex:0]mutableCopy];
NSLog(#"notification_id=%#",notification_id);
item_id= [[[request valueForKey:#"item_id"]objectAtIndex:0]mutableCopy];;
NSLog(#"item_id=%#",item_id);
frnd_count.text=[NSString stringWithFormat:#"%#",frndcount];
if (deleteIndexPath==0) {
[request removeObjectAtIndex:deleteIndexPath.row];
[self.msg_table deleteRowsAtIndexPaths:[NSArray arrayWithObject:deleteIndexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"Error: %#", error);
}];
}
Your request object is a NSArray object, that is immutable. you should change it to NSMutableArray and your problem is resolved.
Update
I don't know how you are initialising this object, but if you are doing something like this:
NSMutableArray *request = someData;
the referencing object may be not mutable, so you should resolve it doing this:
NSMutableArray *request = [someData mutableCopy];
Now, you have a mutable data.
when I execute this line of code in iOS 8.3 this line crashes:
NSArray *results = [self executeFetchRequest:request inContext:context];
here is the entire function which fails:
+ (id) executeFetchRequestAndReturnFirstObject:(NSFetchRequest *)request inContext:(NSManagedObjectContext *)context
{
[request setFetchLimit:1];
NSArray *results = [self executeFetchRequest:request inContext:context];
if ([results count] == 0)
{
return nil;
}
return [results objectAtIndex:0];
}
the above function is called by:
+ (id)findFirstByAttribute:(NSString *)attribute withValue:(id)searchValue inContext:(NSManagedObjectContext *)context
{
NSFetchRequest *request = [self requestFirstByAttribute:attribute withValue:searchValue inContext:context];
[request setPropertiesToFetch:[NSArray arrayWithObject:attribute]];
return [self executeFetchRequestAndReturnFirstObject:request inContext:context];
}
It is worth noting that I am very new to iOS programming so please go easy on me, the question may not be the best and there may not be much backing code but this is due to my lack of knowledge in iOS. My android questions are generally much better than this :P If I am able to add any more detail, I will add more as I can, the crash log is below
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Bad fetch request
(NSManagedObjectResultType not compatible with contents of
propertiesToFetch)'
* First throw call stack: ( 0 CoreFoundation 0x0000000111d7dc65 exceptionPreprocess + 165 1 libobjc.A.dylib
0x0000000110fafbb7 objc_exception_throw + 45 2 CoreData
0x00000001112ecb6e -[NSSQLGenerator
newSQLStatementForRequest:ignoreInheritance:countOnly:nestingLevel:] +
1646 3 CoreData 0x00000001112d8dc4
-[NSSQLAdapter _statementForFetchRequest:ignoreInheritance:countOnly:nestingLevel:] + 244 4 CoreData 0x00000001111f0e0c
-[NSSQLAdapter _newSelectStatementWithFetchRequest:ignoreInheritance:] + 316 5 CoreData 0x00000001111f0a86 -[NSSQLCore newRowsForFetchPlan:] + 118 6 CoreData 0x00000001111f033c -[NSSQLCore objectsForFetchRequest:inContext:] +
524 7 CoreData 0x00000001111efdbb
-[NSSQLCore executeRequest:withContext:error:] + 299 8 CoreData 0x00000001112caa6c __65-[NSPersistentStoreCoordinator
executeRequest:withContext:error:]_block_invoke + 3356 9 CoreData
0x00000001112d3c30 gutsOfBlockToNSPersistentStoreCoordinatorPerform +
192 10 libdispatch.dylib 0x0000000114e29614
_dispatch_client_callout + 8 11 libdispatch.dylib 0x0000000114e0f002 _dispatch_barrier_sync_f_invoke + 365 12 CoreData
0x00000001112c5245 _perform + 197 13 CoreData
0x00000001111efa58 -[NSPersistentStoreCoordinator
executeRequest:withContext:error:] + 504 14 CoreData
0x00000001111ee2ca -[NSManagedObjectContext
executeFetchRequest:error:] + 586 15 HawkExpress
0x000000010e52438e +[NSManagedObject(MagicalRecord)
executeFetchRequest:inContext:] + 62 16 HawkExpress
0x000000010e52446e +[NSManagedObject(MagicalRecord)
executeFetchRequestAndReturnFirstObject:inContext:] + 78 17
HawkExpress 0x000000010e5261fc
+[NSManagedObject(MagicalRecord) findFirstByAttribute:withValue:inContext:] + 140 18 HawkExpress
0x000000010e526274 +[NSManagedObject(MagicalRecord)
findFirstByAttribute:withValue:] + 100 19 HawkExpress
0x000000010e52aa54 +[FavouritesManager doesFavouriteExist:] + 84 20
HawkExpress 0x000000010e4de4a7
-[BookCabViewController tableView:cellForRowAtIndexPath:] + 2087 21 UIKit 0x00000001124b9a28 -[UITableView
_createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 508 22 UIKit 0x0000000112498248 -[UITableView
_updateVisibleCellsNow:isRecursive:] + 2853 23 UIKit 0x00000001124ae8a9 -[UITableView layoutSubviews] + 210 24 UIKit
0x0000000112438a2b -[UIView(CALayerDelegate) layoutSublayersOfLayer:]
+ 536 25 QuartzCore 0x000000010fdfbec2 -[CALayer layoutSublayers] + 146 26 QuartzCore 0x000000010fdf06d6 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE +
380 27 QuartzCore 0x000000010fdf0546
_ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24 28 QuartzCore 0x000000010fd5c886
_ZN2CA7Context18commit_transactionEPNS_11TransactionE + 242 29 QuartzCore 0x000000010fd5da3a
_ZN2CA11Transaction6commitEv + 462 30 QuartzCore 0x000000010fd5e0eb
_ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 89 31 CoreFoundation 0x0000000111cb0ca7
__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION + 23 32 CoreFoundation 0x0000000111cb0c00
__CFRunLoopDoObservers + 368 33 CoreFoundation 0x0000000111ca6a33 __CFRunLoopRun + 1123 34 CoreFoundation
0x0000000111ca6366 CFRunLoopRunSpecific + 470 35 GraphicsServices
0x0000000114a34a3e GSEventRunModal + 161 36 UIKit
0x00000001123b8900 UIApplicationMain + 1282 37 HawkExpress
0x000000010e4baa23 main + 99 38 libdyld.dylib
0x0000000114e5d145 start + 1 ) libc++abi.dylib: terminating with
uncaught exception of type NSException (lldb)
You need to check if the NSArray results is nil before you can do a count.
if (array != nil) {
NSUInteger count = [array count]; // May be 0 if the object has been deleted.
//
}
else {
// Deal with error.
}
See https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreData/Articles/cdFetching.html
Your NSFetchRequest object is probably not constructed correctly.
Here is a valid NSFetchRequest example. Find plenty more by googling "NSFetchRequest example".
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == %#", aTitle]; //<----- (a)
[request setEntity:[NSEntityDescription entityForName:#"Person" inManagedObjectContext:moc]];
[request setPredicate:predicate];
Be careful at (a), the string must strictly follow the predicate format string pattern (see NSPrediate class reference), name must be a property of Person entity in your managed object model
And the problem is in this part
NSFetchRequest *request = [self requestFirstByAttribute:attribute withValue:searchValue inContext:context];
[request setPropertiesToFetch:[NSArray arrayWithObject:attribute]];
So, post the code for method [self requestFirstByAttribute... ] if still not resolved.
tried to comment out the line [request setPropertiesToFetch:[NSArray arrayWithObject:attribute]];?
'Bad fetch request (NSManagedObjectResultType not compatible with contents of propertiesToFetch)' means, that you seem to expect the default NSFetchRequestResultType (NSManagedObjectResultType). But you request not to fetch the complete Entity, but only ONE attribute (why, just by the way? Your method provide an expected value and gives only one attribute to fetch).
My solution to this:
- (id)findEntityNamed:(NSString*)entity withKeyPath:(NSString*)path equalTo:(id)value
{
NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:entity
inManagedObjectContext:context]];
NSPredicate* predicate =
[NSComparisonPredicate predicateWithLeftExpression:[NSExpression expressionForKeyPath:path]
rightExpression:[NSExpression expressionForConstantValue:value]
modifier:NSDirectPredicateModifier
type:NSEqualToPredicateOperatorType
options:0];
[fetchRequest setPredicate:predicate];
[fetchRequest setFetchLimit:1]; // ONLY 1 OBJECT IS FETCHED!
NSError* err = nil;
NSArray* results = [context executeFetchRequest:fetchRequest error:&err];
[fetchRequest release];
if( err )
{
// do logging stuff etc.
}
if( [results count] < 1 )
return nil;
return [results lastObject];
}
you can try this and tell if this is more like you was looking for
For the below code snippet:
error occurs at setObject: forKey:
response <--is an NSDictionary
if(response){
NSMutableArray *lifeArray = [[NSMutableArray alloc] init];
NSMutableDictionary *responseDict = [[NSMutableDictionary alloc] init];
responseDict = (NSMutableDictionary *)[response mutableCopy];
[responseDict setObject:#"life" forKey:#"label"]; <-- Error here
}
Note that variable responseDict is NSMutableDictionary since copied via mutableCopy.
Error message:
2014-11-12 12:16:08.534 Lifetape[84381:508759] -[__NSCFArray setObject:forKey:]: unrecognized selector sent to instance 0x7a296700
2014-11-12 12:16:08.536 Lifetape[84381:508759] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFArray setObject:forKey:]: unrecognized selector sent to instance 0x7a296700'
*** First throw call stack:
(
0 CoreFoundation 0x028fbdf6 __exceptionPreprocess + 182
1 libobjc.A.dylib 0x02557a97 objc_exception_throw + 44
2 CoreFoundation 0x02903a75 -[NSObject(NSObject) doesNotRecognizeSelector:] + 277
3 CoreFoundation 0x0284c9c7 ___forwarding___ + 1047
4 CoreFoundation 0x0284c58e _CF_forwarding_prep_0 + 14
5 Lifetape 0x000dfb83 __50-[LTTimeLineTableViewController getTimeIntervals:]_block_invoke + 307
6 Lifetape 0x0014cedb -[MethodInvoker maybeInvokeCallback] + 395
7 Lifetape 0x0014d19f -[MethodInvoker receiveResultWithError:andResult:] + 399
8 Lifetape 0x00143e38 -[MeteorClient(Connection) livedata_result:] + 1544
9 Lifetape 0x00138674 __54-[MeteorClient(Connection) initConnectionWithOptions:]_block_invoke_3 + 2660
10 Lifetape 0x0014b2b5 -[MeteorClient didReceiveMessage:] + 197
11 Lifetape 0x0014eb7d -[ObjectiveDDP webSocket:didReceiveMessage:] + 269
12 Lifetape 0x0015d986 __30-[SRWebSocket _handleMessage:]_block_invoke + 102
13 libdispatch.dylib 0x031e941a _dispatch_call_block_and_release + 15
14 libdispatch.dylib 0x03209e1f _dispatch_client_callout + 14
15 libdispatch.dylib 0x031f0981 _dispatch_main_queue_callback_4CF + 610
16 CoreFoundation 0x02855f3e __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 14
17 CoreFoundation 0x02814d40 __CFRunLoopRun + 2256
18 CoreFoundation 0x028141ab CFRunLoopRunSpecific + 443
19 CoreFoundation 0x02813fdb CFRunLoopRunInMode + 123
20 GraphicsServices 0x051a524f GSEventRunModal + 192
21 GraphicsServices 0x051a508c GSEventRun + 104
22 UIKit 0x00f41e16 UIApplicationMain + 1526
23 Lifetape 0x000ce36d main + 141
24 libdyld.dylib 0x03235ac9 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Here your response dictionary is a NSDictionary type collection so it does not have any selector like setObject, that's why it is giving you this error use
if(response && [response isKindOfClass:[NSDictionary class]]){
NSMutableArray *lifeArray = [[NSMutableArray alloc] init];
NSMutableDictionary *responseDict = [NSMutableDictionary dictionaryWithDictionary:response];
[responseDict setObject:#"life" forKey:#"label"];
}
and it will work but make sure response is your dictionary type object. as the error you have posted clearly says that your response is an array not a dictionary.
Your response looks like NSArray class so try below code.
if([response isKindOfClass:[NSArray Class]]){
NSLog(#"Array");
}
else if([response isKindOfClass:[NSDictionary Class]]){
NSLog(#"Dictionary");
}
Now manage your code as per log.
My app is working great, the only issue i have right now it's with the live data viewer, if nothing is happening the XML file is empty, and the app displays nothing to show right now, if it has 2 or 2000 events happening, it displays in my live data viewer, if there is only a single event occurring my app crashes when i got to that view.
I have compared the XML structures and they are the same for 1 or 2+ events.
I have included below my XML parser method, my cellForRowAtIndexPath and my numberOfRows method.
Is there anyone out there that can see what's the issue? I remind you again, this only crashes if my XML file has a single Match node. Works fine with 0 or 100000 but not with 1.
At the end you will also find the crash report, i hope it's useful in finding the problem and fixing it.
Thank you.
-(void) parseXMLLiveMatch
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"something.xml"]];
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *xmlString = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSDictionary *xml = [NSDictionary dictionaryWithXMLString:xmlString];
NSMutableArray *items = [xml objectForKey:#"Match"];
NSMutableArray *newLiveMatchArray = [[NSMutableArray alloc] init];
for (NSDictionary *dict in items) {
NSLog(#"%# %#", [dict class], dict);
LiveMatchObject *myMatches = [LiveMatchObject matchesFromXMLDictionary:dict];
[newLiveMatchArray addObject:myMatches];
}
NSNull *nullValue = [NSNull null];
[newLiveMatchArray insertObject:nullValue atIndex:0];
[self setTableDataLiveMatch:newLiveMatchArray];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"LiveIdent";
LiveViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
LiveMatchObject *item = [tableDataLiveMatch objectAtIndex:(int)([indexPath row]/2)];
...
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return tableDataLiveMatch.count * 2;
}
2014-02-17 14:40:56.419 Liga Zon Sagres Companion[2539:70b] __NSCFString HomeGoals
2014-02-17 14:40:56.420 Liga Zon Sagres Companion[2539:70b] -[__NSCFString objectForKeyedSubscript:]: unrecognized selector sent to instance 0x10d03d7f0
2014-02-17 14:40:56.424 Liga Zon Sagres Companion[2539:70b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString objectForKeyedSubscript:]: unrecognized selector sent to instance 0x10d03d7f0'
*** First throw call stack:
(
0 CoreFoundation 0x00000001019df795 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x0000000101742991 objc_exception_throw + 43
2 CoreFoundation 0x0000000101a70bad -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x00000001019d109d ___forwarding___ + 973
4 CoreFoundation 0x00000001019d0c48 _CF_forwarding_prep_0 + 120
5 Liga Zon Sagres Companion 0x00000001000014da +[LiveMatchObject matchesFromXMLDictionary:] + 138
6 Liga Zon Sagres Companion 0x0000000100003da6 -[LiveTableViewController parseXMLLiveMatch] + 790
7 Liga Zon Sagres Companion 0x0000000100003a48 -[LiveTableViewController viewWillAppear:] + 88
8 UIKit 0x00000001004943f4 -[UIViewController _setViewAppearState:isAnimating:] + 394
9 UIKit 0x00000001004c0ce5 -[UITabBarController transitionFromViewController:toViewController:transition:shouldSetSelected:] + 524
10 UIKit 0x00000001004bd155 -[UITabBarController _setSelectedViewController:] + 259
11 UIKit 0x00000001004c046c -[UITabBarController _tabBarItemClicked:] + 248
12 UIKit 0x00000001003a6096 -[UIApplication sendAction:to:from:forEvent:] + 80
13 UIKit 0x00000001003a6044 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 17
14 UIKit 0x00000001005fb4cc -[UITabBar _sendAction:withEvent:] + 420
15 UIKit 0x00000001003a60ae -[UIApplication sendAction:to:from:forEvent:] + 104
16 UIKit 0x00000001003a6044 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 17
17 UIKit 0x000000010047a450 -[UIControl _sendActionsForEvents:withEvent:] + 203
18 UIKit 0x00000001003a6096 -[UIApplication sendAction:to:from:forEvent:] + 80
19 UIKit 0x00000001003a6044 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 17
20 UIKit 0x000000010047a450 -[UIControl _sendActionsForEvents:withEvent:] + 203
21 UIKit 0x00000001004799c0 -[UIControl touchesEnded:withEvent:] + 530
22 UIKit 0x00000001003dac15 -[UIWindow _sendTouchesForEvent:] + 701
23 UIKit 0x00000001003db633 -[UIWindow sendEvent:] + 988
24 UIKit 0x00000001003b4fa2 -[UIApplication sendEvent:] + 211
25 UIKit 0x00000001003a2d7f _UIApplicationHandleEventQueue + 9549
26 CoreFoundation 0x000000010196eec1 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
27 CoreFoundation 0x000000010196e792 __CFRunLoopDoSources0 + 242
28 CoreFoundation 0x000000010198a61f __CFRunLoopRun + 767
29 CoreFoundation 0x0000000101989f33 CFRunLoopRunSpecific + 467
30 GraphicsServices 0x000000010300b3a0 GSEventRunModal + 161
31 UIKit 0x00000001003a5043 UIApplicationMain + 1010
32 Liga Zon Sagres Companion 0x000000010001fce3 main + 115
33 libdyld.dylib 0x000000010232b5fd start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
Cheers and thank you.
As resquested:
#implementation LiveMatchObject
#synthesize homeGoals, awayGoals, homeName, awayName, matchDate, matchMinute, matchStatus, homeTeamLogo, awayTeamLogo, spectators, round, homeStartingGoalie, homeStartingDefense, homeStartingMiddlefield, homeStartingFoward, homeFormation, awayStartingGoalie, awayStartingDefense, awayStartingMiddlefield, awayStartingFoward, awayFormation;
+(LiveMatchObject *)matchesFromXMLDictionary:(NSDictionary *)dict{
LiveMatchObject *object =[[LiveMatchObject alloc]init];
object.homeGoals = dict[#"HomeGoals"];
object.awayGoals = dict[#"AwayGoals"];
object.homeName = dict[#"Hometeam"];
object.awayName = dict[#"Awayteam"];
object.matchDate = dict[#"Date"];
object.matchMinute = dict[#"Time"];
object.matchStatus = [UIImage imageNamed:dict[#"Time"]];
object.homeTeamLogo = [UIImage imageNamed:dict[#"HomeTeam_Id"]];
object.awayTeamLogo = [UIImage imageNamed:dict[#"AwayTeam_Id"]];
object.spectators = dict[#"Spectators"];
object.round = dict[#"Round"];
object.homeFormation = dict[#"HomeTeamFormation"];
object.homeStartingGoalie = dict[#"HomeLineupGoalkeeper"];
object.homeStartingMiddlefield = dict[#"HomeLineupMidfield"];
object.homeStartingFoward = dict[#"HomeLineupForward"];
object.awayFormation = dict[#"AwayTeamFormation"];
object.awayStartingGoalie = dict[#"AwayLineupGoalkeeper"];
object.awayStartingMiddlefield = dict[#"AwayLineupMidfield"];
object.awayStartingFoward = dict[#"AwayLineupForward"];
return object;
}
#end
The XML
<CREPERR.COM >
<Match>
<Id>327080</Id>
<Date>2014-02-17T12:00:00-08:00</Date>
<League>Primeira Liga</League>
<Round>19</Round>
<Spectators/>
<Hometeam>Estoril-Praia</Hometeam>
<HomeTeam_Id>529</HomeTeam_Id>
<Awayteam>Braga</Awayteam>
<AwayTeam_Id>521</AwayTeam_Id>
<Time>9'</Time>
<HomeGoals>0</HomeGoals>
<AwayGoals>0</AwayGoals>
<HomeGoalDetails/>
<AwayGoalDetails/>
<HomeLineupGoalkeeper>Vagner</HomeLineupGoalkeeper>
<AwayLineupGoalkeeper>Eduardo</AwayLineupGoalkeeper>
<HomeLineupDefense>Yohan Tavares; Mano; Babanco; Ruben;</HomeLineupDefense>
<AwayLineupDefense>
Nurio; Aleksandar Miljkovic; Nuno André Coelho; Vincent Sasso;
</AwayLineupDefense>
<HomeLineupMidfield>
Javier Balboa; Goebel Evandro; Carlitos; Diogo Amado; Goncalo;
</HomeLineupMidfield>
<AwayLineupMidfield>
Custodio; Mauro; Leandro Kappel; Felipe Pardo; Alan;
</AwayLineupMidfield>
<HomeLineupForward>Seba;</HomeLineupForward>
<AwayLineupForward>Raul Andrei Rusescu;</AwayLineupForward>
<HomeSubDetails/>
<AwaySubDetails/>
<HomeTeamFormation>4-2-3-1</HomeTeamFormation>
<AwayTeamFormation>4-2-3-1</AwayTeamFormation>
<Location>Estádio António Coimbra da Mota</Location>
<Stadium>Estádio António Coimbra da Mota</Stadium>
<HomeTeamYellowCardDetails/>
<AwayTeamYellowCardDetails/>
<HomeTeamRedCardDetails/>
<AwayTeamRedCardDetails/>
</Match>
<AccountInformation>
Data requested at 2/17/2014
</AccountInformation>
</CREPERR.COM>
You are crashing because when there is only one object in your array the dict object is an NSString, not an NSDictionary. NSString does not respond the the string[#"Something"] interface, and therefore is crashing your application.
One way to test for this is:
+(LiveMatchObject *)matchesFromXMLDictionary:(NSDictionary *)dict{
if([dict isKindOfClass:[NSDictionary class]])
{
//This is a valid dictionary
}
else
{
//This is not a dictionary object, do something different
}
}
Why you are getting an NSString here instead of an NSDictionary I have no idea, and how you deal with it to get your data out in the same fashion is another question. You are going to have to set a breakpoint in there and see what NSString you are getting and what to do with it.