I need to add an empty object to index 0 and index 1 of an array being populated with data from a third party XML feed.
This is my parseXML method, it works.
-(void) parseXML{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"APIKEYHERECANTSHOW YOU"]];
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *xmlString = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSLog(#"The string : %#", xmlString);
NSDictionary *xml = [NSDictionary dictionaryWithXMLString:xmlString];
NSLog(#"The dict:%#", xml);
NSMutableDictionary *PageItem = [xml objectForKey:#"TeamLeagueStanding"];
NSLog(#"PageItem: %#", PageItem);
NSMutableArray *items = [xml objectForKey:#"TeamLeagueStanding"];
NSNull *nullValue = [NSNull null];
[items insertObject:nullValue atIndex:0]; <- THIS MAKES MY APP CRASH
NSLog(#"The array: %#", items);
[self setTableData:items];
}
But when i run this i get a crash with the console output:
2014-02-03 21:24:09.063 Liga Zon Sagres Companion[9645:70b] -[NSNull objectForKey:]: unrecognized selector sent to instance 0x101a85b40
2014-02-03 21:24:09.066 Liga Zon Sagres Companion[9645:70b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull objectForKey:]: unrecognized selector sent to instance 0x101a85b40'
*** First throw call stack:
(
0 CoreFoundation 0x000000010192a795 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010168d991 objc_exception_throw + 43
2 CoreFoundation 0x00000001019bbbad -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x000000010191c09d ___forwarding___ + 973
4 CoreFoundation 0x000000010191bc48 _CF_forwarding_prep_0 + 120
5 Liga Zon Sagres Companion 0x000000010000ee20 -[StandingsTableViewController tableView:cellForRowAtIndexPath:] + 256
6 UIKit 0x00000001003bbb8a -[UITableView _createPreparedCellForGlobalRow:withIndexPath:] + 348
7 UIKit 0x00000001003a3836 -[UITableView _updateVisibleCellsNow:] + 2297
8 UIKit 0x00000001003b4381 -[UITableView layoutSubviews] + 207
9 UIKit 0x000000010034bb27 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 354
10 QuartzCore 0x0000000102081a22 -[CALayer layoutSublayers] + 151
11 QuartzCore 0x0000000102076589 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 363
12 QuartzCore 0x0000000102081956 -[CALayer layoutIfNeeded] + 162
13 UIKit 0x00000001003ebfc2 -[UIViewController window:setupWithInterfaceOrientation:] + 264
14 UIKit 0x000000010032ab4d -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:isRotating:] + 4360
15 UIKit 0x0000000100329a3f -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:] + 36
16 UIKit 0x000000010032998f -[UIWindow _setRotatableViewOrientation:updateStatusBar:duration:force:] + 101
17 UIKit 0x0000000100328c9e -[UIWindow _updateToInterfaceOrientation:duration:force:] + 377
18 UIKit 0x00000001003dfd4a -[UIViewController _tryBecomeRootViewControllerInWindow:] + 147
19 UIKit 0x0000000100323a87 -[UIWindow addRootViewControllerViewIfPossible] + 506
20 UIKit 0x0000000100323bd5 -[UIWindow _setHidden:forced:] + 275
21 UIKit 0x000000010032cca2 -[UIWindow makeKeyAndVisible] + 51
22 UIKit 0x00000001002eb0c8 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1449
23 UIKit 0x00000001002eebe8 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 660
24 UIKit 0x00000001002ffaab -[UIApplication handleEvent:withNewEvent:] + 3092
25 UIKit 0x00000001002fff1e -[UIApplication sendEvent:] + 79
26 UIKit 0x00000001002f02be _UIApplicationHandleEvent + 618
27 GraphicsServices 0x0000000102578bb6 _PurpleEventCallback + 762
28 GraphicsServices 0x000000010257867d PurpleEventCallback + 35
29 CoreFoundation 0x00000001018ac819 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 41
30 CoreFoundation 0x00000001018ac5ee __CFRunLoopDoSource1 + 478
31 CoreFoundation 0x00000001018d5ab3 __CFRunLoopRun + 1939
32 CoreFoundation 0x00000001018d4f33 CFRunLoopRunSpecific + 467
33 UIKit 0x00000001002ee4bd -[UIApplication _run] + 609
34 UIKit 0x00000001002f0043 UIApplicationMain + 1010
35 Liga Zon Sagres Companion 0x0000000100011f93 main + 115
36 libdyld.dylib 0x0000000102f815fd start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Any ideas how to solve this? Thank you.
The error is coming from your StandingsTableViewController tableView:cellForRowAtIndexPath: method. Your data is giving you an NSNull instance where you expect an NSDictionary.
Since you explicitly add the NSNull object you need to update your cellForRow... method to check to see if the object is an NSNull instance before assuming it is an NSDictionary.
Something like this:
NSDictionary *data = self.tableData[someIndex];
if ([data isKindOfClass:[NSDictionary class]]) {
// process the data as usual
} else {
// This is probably the NSNull object, ignore it or handle appropriately
}
Related
I am trying to add object to the array from a dictionary . In else part I am getting this error
mutating method sent to immutable object'
NSMutableDictionary *selectedDict = [NSMutableDictionary new];
[selectedDict setObject:editedLineItem forKey:#"Text"];
[selectedDict setObject:#"fa-check" forKey:#"IconClass"];
NSMutableArray *tagListDictionary = [NSMutableArray new];
[tagListDictionary addObject:selectedTagsArray];
LineItemsStorage *linestorage = [LineItemsStorage sharedManager];
if(![linestorage.packagesArray valueForKey:#"Id"])
{
[linestorage.selectedLineItemsAndTagsArray addObject:selectedDict];
}
else{ [[linestorage.packagesArray valueForKey:#"LineItems"]addObject:[NSMutableArray arrayWithObject:selectedDict]];
}
-[NSCFArray insertObject:atIndex:]: mutating method sent to immutable object'
*** First throw call stack:
(
0 CoreFoundation 0x00000001154a1d85 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x0000000114f15deb objc_exception_throw + 48
2 CoreFoundation 0x00000001154a1cbd +[NSException raise:format:] + 205
3 CoreFoundation 0x0000000115497b0a -[__NSCFArray insertObject:atIndex:] + 106
4 FlatPebble 0x000000010f276014 -[LineItemViewController okayAction] + 836
5 UIKit 0x0000000113809a8d -[UIApplication sendAction:to:from:forEvent:] + 92
6 UIKit 0x000000011397ce67 -[UIControl sendAction:to:forEvent:] + 67
7 UIKit 0x000000011397d143 -[UIControl _sendActionsForEvents:withEvent:] + 327
8 UIKit 0x000000011397c263 -[UIControl touchesEnded:withEvent:] + 601
9 UIKit 0x000000011387c99f -[UIWindow _sendTouchesForEvent:] + 835
10 UIKit 0x000000011387d6d4 -[UIWindow sendEvent:] + 865
11 UIKit 0x0000000113828dc6 -[UIApplication sendEvent:] + 263
12 UIKit 0x0000000113802553 _UIApplicationHandleEventQueue + 6660
13 CoreFoundation 0x00000001153c7301 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION + 17
14 CoreFoundation 0x00000001153bd22c __CFRunLoopDoSources0 + 556
15 CoreFoundation 0x00000001153bc6e3 __CFRunLoopRun + 867
16 CoreFoundation 0x00000001153bc0f8 CFRunLoopRunSpecific + 488
17 GraphicsServices 0x0000000116e5cad2 GSEventRunModal + 161
18 UIKit 0x0000000113807f09 UIApplicationMain + 171
19 *********** 0x000000010f348c2f main + 111
20 libdyld.dylib 0x0000000115d9992d start + 1
)
Use this code
NSMutableDictionary *selectedDict = [[NSMutableDictionary new]mutableCopy];
[selectedDict setObject:editedLineItem forKey:#"Text"];
[selectedDict setObject:#"fa-check" forKey:#"IconClass"];
NSMutableArray *tagListDictionary = [[NSMutableArray new]mutableCopy];
[tagListDictionary addObject:selectedTagsArray];
LineItemsStorage *linestorage = [LineItemsStorage sharedManager];
if(![linestorage.packagesArray valueForKey:#"Id"])
{
[linestorage.selectedLineItemsAndTagsArray addObject:selectedDict];
}
else{ [[linestorage.packagesArray valueForKey:#"LineItems"]addObject:[NSMutableArray arrayWithObject:selectedDict]];
}
Assuming your packagesArray contains an array containing one or more objects that have a LineItems property (that happens to also be an array); your problem is here:
[[linestorage.packagesArray valueForKey:#"LineItems"]addObject:[NSMutableArray arrayWithObject:selectedDict]]
Breaking it down it is equivalent to:
NSArray* packagesLineItems = [linestorage.packagesArray valueForKey:#"LineItems"];
NSMutableArray* selected = [NSMutableArray arrayWithObject:selectedDict];
[packagesLineItems addObject:selected];
So your problem is either the return type of valueForKey (when called on an array), or the action you're trying to do on it.
Here's my code,
for (int i=0; i<=[selfLinksArray count]; i++) {
NSString *temp = selfLinksArray[i];
NSURL *tempURL = [NSURL URLWithString:temp ];
NSLog(#"NSURL:%#",tempURL);
NSData *tempData = [NSData dataWithContentsOfURL:tempURL];
NSError *error = nil;
NSDictionary *tempDict = [NSJSONSerialization JSONObjectWithData:tempData options:0 error:&error];
NSDictionary *volumeInfoDict = [tempDict objectForKey:#"volumeInfo"];
titleArray[i]=[volumeInfoDict objectForKey:#"title"];
}
Xcode shows me this error
[__NSArrayI length]: unrecognized selector sent to instance 0x7fdf334f0bc0
2016-01-19 16:12:34.937 BookFindr[7775:449799] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI length]: unrecognized selector sent to instance 0x7fdf334f0bc0'
*** First throw call stack:
(
0 CoreFoundation 0x000000010f34be65 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010edc4deb objc_exception_throw + 48
2 CoreFoundation 0x000000010f35448d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x000000010f2a190a ___forwarding___ + 970
4 CoreFoundation 0x000000010f2a14b8 _CF_forwarding_prep_0 + 120
5 CoreFoundation 0x000000010f32e261 _CFURLCreateWithURLString + 81
6 Foundation 0x000000010e97a465 -[NSURL(NSURL) initWithString:relativeToURL:] + 349
7 Foundation 0x000000010e97a2e2 +[NSURL(NSURL) URLWithString:relativeToURL:] + 59
8 BookFindr 0x000000010e8bf9ab -[tabResTableViewController viewDidLoad] + 219
9 UIKit 0x000000010f88ef98 -[UIViewController loadViewIfRequired] + 1198
10 UIKit 0x000000010f894f4f -[UIViewController __viewWillAppear:] + 120
11 UIKit 0x000000010f8c4e44 -[UINavigationController _startCustomTransition:] + 1203
12 UIKit 0x000000010f8d523f -[UINavigationController _startDeferredTransitionIfNeeded:] + 712
13 UIKit 0x000000010f8d63af -[UINavigationController __viewWillLayoutSubviews] + 57
14 UIKit 0x000000010fa7cff7 -[UILayoutContainerView layoutSubviews] + 248
15 UIKit 0x000000010f7af4a3 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 703
16 QuartzCore 0x000000011327b59a -[CALayer layoutSublayers] + 146
17 QuartzCore 0x000000011326fe70 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 366
18 QuartzCore 0x000000011326fcee _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
19 QuartzCore 0x0000000113264475 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 277
20 QuartzCore 0x0000000113291c0a _ZN2CA11Transaction6commitEv + 486
21 UIKit 0x000000010f6f2f7c _UIApplicationHandleEventQueue + 7329
22 CoreFoundation 0x000000010f277a31 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
23 CoreFoundation 0x000000010f26d95c __CFRunLoopDoSources0 + 556
24 CoreFoundation 0x000000010f26ce13 __CFRunLoopRun + 867
25 CoreFoundation 0x000000010f26c828 CFRunLoopRunSpecific + 488
26 GraphicsServices 0x0000000112b08ad2 GSEventRunModal + 161
27 UIKit 0x000000010f6f8610 UIApplicationMain + 171
28 BookFindr 0x000000010e8c101f main + 111
29 libdyld.dylib 0x0000000111a8792d start + 1
30 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
I have imported selfLinkArray from another viewController. I want to fetch various titles which are present in VolumeInfo dictionary. This dictionary is present in each individual link in selfLinksArray. Please help me with this error. Thanks in Advance.
Let's analyze your error and your backtrace :
-[__NSArrayI length]: unrecognized selector sent to instance 0x7fdf334f0bc0'
The issue is written here: the length method is called on an NSArray object.
Wait, this method is not even written in this sample! Don't worry, let's analyze it.
6 Foundation 0x000000010e97a465
-[NSURL(NSURL) initWithString:relativeToURL:] + 349
7 Foundation 0x000000010e97a2e2 +[NSURL(NSURL) URLWithString:relativeToURL:]
The crash log indicates that the crash occurs when you try to init the NSURL object. The only parameter of this init method is a NSString object. But are we sure that temp is really a NSString object ?
This variable is casted without checking if it's really an NSString object. It can be anthing, for example... the NSArray which receive a call to the length method. Also, this method is existing for a NSString object, so the unrecognizer selector error look totally related.
Where do you we call length on this NSString object ? My guess is, according to the backtrace, that URLWithString: call this method to check the NSString length in order to initialize properly the NSURL object.
I am using for in loop to fetch data from plist. But it is showing following exception:
2015-07-16 11:16:43.597 plistNeha[640:60b] -[__NSCFDictionary objectAtIndexedSubscript:]: unrecognized selector sent to instance 0x8d671b0
2015-07-16 11:16:43.721 plistNeha[640:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary objectAtIndexedSubscript:]: unrecognized selector sent to instance 0x8d671b0'
*** First throw call stack:
(
0 CoreFoundation 0x017ed1e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x0156c8e5 objc_exception_throw + 44
2 CoreFoundation 0x0188a243 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
3 CoreFoundation 0x017dd50b ___forwarding___ + 1019
4 CoreFoundation 0x017dd0ee _CF_forwarding_prep_0 + 14
5 plistNeha 0x00002b7d -[sdViewController plistbtn:] + 333
6 libobjc.A.dylib 0x0157e880 -[NSObject performSelector:withObject:withObject:] + 77
7 UIKit 0x0022e3b9 -[UIApplication sendAction:to:from:forEvent:] + 108
8 UIKit 0x0022e345 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 61
9 UIKit 0x0032fbd1 -[UIControl sendAction:to:forEvent:] + 66
10 UIKit 0x0032ffc6 -[UIControl _sendActionsForEvents:withEvent:] + 577
11 UIKit 0x0032f243 -[UIControl touchesEnded:withEvent:] + 641
12 UIKit 0x0026dddd -[UIWindow _sendTouchesForEvent:] + 852
13 UIKit 0x0026e9d1 -[UIWindow sendEvent:] + 1117
14 UIKit 0x002405f2 -[UIApplication sendEvent:] + 242
15 UIKit 0x0022a353 _UIApplicationHandleEventQueue + 11455
16 CoreFoundation 0x0177677f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
17 CoreFoundation 0x0177610b __CFRunLoopDoSources0 + 235
18 CoreFoundation 0x017931ae __CFRunLoopRun + 910
19 CoreFoundation 0x017929d3 CFRunLoopRunSpecific + 467
20 CoreFoundation 0x017927eb CFRunLoopRunInMode + 123
21 GraphicsServices 0x037e15ee GSEventRunModal + 192
22 GraphicsServices 0x037e142b GSEventRun + 104
23 UIKit 0x0022cf9b UIApplicationMain + 1225
24 plistNeha 0x00002e1d main + 141
25 libdyld.dylib 0x01e34701 start + 1
26 ??? 0x00000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
Code:
NSString *path=[[NSBundle mainBundle]pathForResource:#"x" ofType:#"plist"];
ald=[[NSDictionary alloc]initWithContentsOfFile:path];
for(NSDictionary *awq in ald){
NSLog(#"check");
NSString *qqw=#"";
qqw=[awq objectForKey:#"qq"];
NSLog(#"%#",qqw);
}
But, if I am fetching data one by one then it is showing on debugger area. for in loop is also working as it is printing check. May be the line after NSLog(#"check"); is creating some exceptions.
Try this
NSString *path=[[NSBundle mainBundle]pathForResource:#"x" ofType:#"plist"];
NSDictionary *ald=[[NSDictionary alloc]initWithContentsOfFile:path];
for(NSDictionary *awq in [ald allValues]){
NSLog(#"check");
NSString *qqw=#"";
qqw=[awq objectForKey:#"qq"];
NSLog(#"%#",qqw);
}
for in on a dictionary is enumerating its keys, not values. See this question for each loop in objective c for accessing NSMutable dictionary
Try this:
NSString *path=[[NSBundle mainBundle]pathForResource:#"x" ofType:#"plist"];
NSDictionary *plistDictionary = [[NSDictionary alloc]initWithContentsOfFile:path];
for(NSString *key in plistDictionary){
NSDictionary *dictionary = [plistDictionary objectForKey:key];
NSLog(#"%#",[dictionary objectForKey:#"qq"]);
}
I had to change your variable names because it was too confusing to work with 'ald', 'awq', 'qqw' , etc.
This is my code for loading data from sqlite file
- (void) loadInitialData{
// Form the query.
NSString *query = #"select * from tasklist";
// Get the results.
if (self.toDoItems != nil) {
self.toDoItems = nil;
}
NSArray *dbResultArray = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:query]];
//Logging for debug purpose
NSLog(#"Result set starts");
for(NSArray *subArray in dbResultArray) {
NSLog(#"Data in array: %#",subArray);
}
NSLog(#"Result set ends");
self.toDoItems = [[NSMutableArray alloc]initWithArray:dbResultArray];
// Reload the table view.
//[self.tblPeople reloadData];
[self.tableView reloadData];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.dbManager = [[DBManager alloc] initWithDatabaseFilename:#"todotaskdb.sql"];
self.toDoItems = [[NSMutableArray alloc] init];
[self loadInitialData];
}
And I am getting this error using NSLog
2014-11-25 18:24:13.862 ToDoList[3213:60b] Result set ends
2014-11-25 18:24:13.865 ToDoList[3213:60b] -[__NSArrayM itemName]: unrecognized selector sent to instance 0x8c996f0
2014-11-25 18:24:13.900 ToDoList[3213:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM itemName]: unrecognized selector sent to instance 0x8c996f0'
*** First throw call stack:
(
0 CoreFoundation 0x018dc1e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x0165b8e5 objc_exception_throw + 44
2 CoreFoundation 0x01979243 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
3 CoreFoundation 0x018cc50b ___forwarding___ + 1019
4 CoreFoundation 0x018cc0ee _CF_forwarding_prep_0 + 14
5 ToDoList 0x00004882 -[XYZToDoListTableViewController tableView:cellForRowAtIndexPath:] + 306
6 UIKit 0x0041411f -[UITableView _createPreparedCellForGlobalRow:withIndexPath:] + 412
7 UIKit 0x004141f3 -[UITableView _createPreparedCellForGlobalRow:] + 69
8 UIKit 0x003f5ece -[UITableView _updateVisibleCellsNow:] + 2428
9 UIKit 0x0040a6a5 -[UITableView layoutSubviews] + 213
10 UIKit 0x0038a964 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 355
11 libobjc.A.dylib 0x0166d82b -[NSObject performSelector:withObject:] + 70
12 QuartzCore 0x03d4745a -[CALayer layoutSublayers] + 148
13 QuartzCore 0x03d3b244 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
14 QuartzCore 0x03d473a5 -[CALayer layoutIfNeeded] + 160
15 UIKit 0x0044cae3 -[UIViewController window:setupWithInterfaceOrientation:] + 304
16 UIKit 0x00362aa7 -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:isRotating:] + 5212
17 UIKit 0x00361646 -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:] + 82
18 UIKit 0x00361518 -[UIWindow _setRotatableViewOrientation:updateStatusBar:duration:force:] + 117
19 UIKit 0x003615a0 -[UIWindow _setRotatableViewOrientation:duration:force:] + 67
20 UIKit 0x0036063a __57-[UIWindow _updateToInterfaceOrientation:duration:force:]_block_invoke + 120
21 UIKit 0x0036059c -[UIWindow _updateToInterfaceOrientation:duration:force:] + 400
22 UIKit 0x003612f3 -[UIWindow setAutorotates:forceUpdateInterfaceOrientation:] + 870
23 UIKit 0x003648e6 -[UIWindow setDelegate:] + 449
24 UIKit 0x0043eb77 -[UIViewController _tryBecomeRootViewControllerInWindow:] + 180
25 UIKit 0x0035a474 -[UIWindow addRootViewControllerViewIfPossible] + 591
26 UIKit 0x0035a5ef -[UIWindow _setHidden:forced:] + 312
27 UIKit 0x0035a86b -[UIWindow _orderFrontWithoutMakingKey] + 49
28 UIKit 0x003653c8 -[UIWindow makeKeyAndVisible] + 65
29 UIKit 0x00315bc0 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 2097
30 UIKit 0x0031a667 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 824
31 UIKit 0x0032ef92 -[UIApplication handleEvent:withNewEvent:] + 3517
32 UIKit 0x0032f555 -[UIApplication sendEvent:] + 85
33 UIKit 0x0031c250 _UIApplicationHandleEvent + 683
34 GraphicsServices 0x038d1f02 _PurpleEventCallback + 776
35 GraphicsServices 0x038d1a0d PurpleEventCallback + 46
36 CoreFoundation 0x01857ca5 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 53
37 CoreFoundation 0x018579db __CFRunLoopDoSource1 + 523
38 CoreFoundation 0x0188268c __CFRunLoopRun + 2156
39 CoreFoundation 0x018819d3 CFRunLoopRunSpecific + 467
40 CoreFoundation 0x018817eb CFRunLoopRunInMode + 123
41 UIKit 0x00319d9c -[UIApplication _run] + 840
42 UIKit 0x0031bf9b UIApplicationMain + 1225
43 ToDoList 0x00004e0d main + 141
44 libdyld.dylib 0x01e25701 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Ironically, if put below line at the end of viewDidLoad method, then it works.
self.dbManager = [[DBManager alloc] initWithDatabaseFilename:#"todotaskdb.sql"];
Can anyone please tell me what is it that I am doing wrong?
Your toDoItems contains Arrays which contains your items! You're may be getting arrays of the single rows in your database, so you would have to fill them into single toDoItems objects first.
Maybe you could use a factory-like pattern with a method like popToDoItemFromRow:(NSArray *)row which returns your toDoItem for this row.
Then fill an new array in your for (NSArray *subArray in dbResultArray) for these single rows. This new array should you use in you cellForRow...
may be like..
- (void) loadInitialData{
// Form the query.
NSString *query = #"select * from tasklist";
// Get the results.
if (self.toDoItems != nil) {
self.toDoItems = nil;
}
NSArray *dbResultArray = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:query]];
if (self.toDoItems) {
[self.toDoItems removeAllObjects];
}
else {
self.toDoItems = [NSMutableArray new];
}
for(NSArray *subArray in dbResultArray) {
[self.toDoItems addObject:[ToDoItem popToDoItemFromRow:subArray]];
}
// Reload the table view.
//[self.tblPeople reloadData];
[self.tableView reloadData];
}
Very strange behaviour...I've used before an NSNumber category called NSNumber+Currencies. Yesterday I've changed everything including core data to NSDecimalNumber so I have now a class NSDecimalNumber+Currencies. There is really no link at all! to NSNumber+Currencies anymore. However if I delete it and try to run my app in the simulator, my app crashes with the message "unrecognized selector sent to instance ..." This instance is a NSDecimalNumber and the methods I use in this category are basically the same as before. And I really import ONLY the NSDecimalNumber+Currencies. But it makes no sense...I've deleted the app from the simulator, cleaned my project, closed Xcode, removed the old category even manually from the build phases but nothing helps..is there another trick? If I leave this old category in it it runs smoothly...
My error log. However after the 2nd run my app doesn't start at all and the error message is a different one:
2014-01-28 11:51:29.458 NetIncome[2341:70b] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 0 beyond bounds for empty array'
*** First throw call stack:
(
0 CoreFoundation 0x01ecf5e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x01abe8b6 objc_exception_throw + 44
2 CoreFoundation 0x01e839c2 -[__NSArrayI objectAtIndex:] + 210
3 CoreData 0x01899c1f -[NSFetchedResultsController objectAtIndexPath:] + 255
4 NetIncome 0x00003dee -[MainCategoriesViewController tableView:cellForRowAtIndexPath:] + 206
5 UIKit 0x003ac61f -[UITableView _createPreparedCellForGlobalRow:withIndexPath:] + 412
6 UIKit 0x003ac6f3 -[UITableView _createPreparedCellForGlobalRow:] + 69
7 UIKit 0x00390774 -[UITableView _updateVisibleCellsNow:] + 2378
8 UIKit 0x0038eb81 -[UITableView _updateVisibleCellsImmediatelyIfNecessary] + 66
9 UIKit 0x0039cb5f -[UITableView _visibleCells] + 35
10 UIKit 0x0039cbb4 -[UITableView visibleCells] + 33
11 UIKit 0x0039fcc0 -[UITableView setSeparatorStyle:] + 115
12 NetIncome 0x000037d4 -[MainCategoriesViewController styleTableView] + 100
13 NetIncome 0x0000300a -[MainCategoriesViewController viewDidLoad] + 1194
14 UIKit 0x003d1318 -[UIViewController loadViewIfRequired] + 696
15 UIKit 0x003f6b15 -[UINavigationController _layoutViewController:] + 39
16 UIKit 0x003f702b -[UINavigationController _updateScrollViewFromViewController:toViewController:] + 235
17 UIKit 0x003f7123 -[UINavigationController _startTransition:fromViewController:toViewController:] + 78
18 UIKit 0x003f809c -[UINavigationController _startDeferredTransitionIfNeeded:] + 645
19 UIKit 0x003f8cb9 -[UINavigationController __viewWillLayoutSubviews] + 57
20 UIKit 0x00532181 -[UILayoutContainerView layoutSubviews] + 213
21 UIKit 0x00328267 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 355
22 libobjc.A.dylib 0x01ad081f -[NSObject performSelector:withObject:] + 70
23 QuartzCore 0x001972ea -[CALayer layoutSublayers] + 148
24 QuartzCore 0x0018b0d4 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
25 QuartzCore 0x00197235 -[CALayer layoutIfNeeded] + 160
26 UIKit 0x003e3613 -[UIViewController window:setupWithInterfaceOrientation:] + 304
27 UIKit 0x00302177 -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:isRotating:] + 5212
28 UIKit 0x00300d16 -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:] + 82
29 UIKit 0x00300be8 -[UIWindow _setRotatableViewOrientation:updateStatusBar:duration:force:] + 117
30 UIKit 0x00300c70 -[UIWindow _setRotatableViewOrientation:duration:force:] + 67
31 UIKit 0x002ffd0a __57-[UIWindow _updateToInterfaceOrientation:duration:force:]_block_invoke + 120
32 UIKit 0x002ffc6c -[UIWindow _updateToInterfaceOrientation:duration:force:] + 400
33 UIKit 0x003009c3 -[UIWindow setAutorotates:forceUpdateInterfaceOrientation:] + 870
34 UIKit 0x00303fb6 -[UIWindow setDelegate:] + 449
35 UIKit 0x003d5737 -[UIViewController _tryBecomeRootViewControllerInWindow:] + 180
36 UIKit 0x002f9c1c -[UIWindow addRootViewControllerViewIfPossible] + 609
37 UIKit 0x002f9d97 -[UIWindow _setHidden:forced:] + 312
38 UIKit 0x002fa02d -[UIWindow _orderFrontWithoutMakingKey] + 49
39 UIKit 0x0030489a -[UIWindow makeKeyAndVisible] + 65
40 UIKit 0x002b7cd0 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1851
41 UIKit 0x002bc3a8 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 824
42 UIKit 0x002d087c -[UIApplication handleEvent:withNewEvent:] + 3447
43 UIKit 0x002d0de9 -[UIApplication sendEvent:] + 85
44 UIKit 0x002be025 _UIApplicationHandleEvent + 736
45 GraphicsServices 0x035202f6 _PurpleEventCallback + 776
46 GraphicsServices 0x0351fe01 PurpleEventCallback + 46
47 CoreFoundation 0x01e4ad65 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 53
48 CoreFoundation 0x01e4aa9b __CFRunLoopDoSource1 + 523
49 CoreFoundation 0x01e7577c __CFRunLoopRun + 2156
50 CoreFoundation 0x01e74ac3 CFRunLoopRunSpecific + 467
51 CoreFoundation 0x01e748db CFRunLoopRunInMode + 123
52 UIKit 0x002bbadd -[UIApplication _run] + 840
53 UIKit 0x002bdd3b UIApplicationMain + 1225
54 NetIncome 0x000027ad main + 141
55 libdyld.dylib 0x031c070d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
EDIT2: And this is the original error message, only shown once and immediately after deleting the relevant files:
2014-01-28 12:00:15.598 NetIncome[2872:70b] -[__NSCFNumber getLocalizedCurrencyString]: unrecognized selector sent to instance 0x8c59720
2014-01-28 12:00:15.602 NetIncome[2872:70b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber getLocalizedCurrencyString]: unrecognized selector sent to instance 0x8c59720'
*** First throw call stack:
(
0 CoreFoundation 0x01ecf5e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x01abe8b6 objc_exception_throw + 44
2 CoreFoundation 0x01f6c903 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
3 CoreFoundation 0x01ebf90b ___forwarding___ + 1019
4 CoreFoundation 0x01ebf4ee _CF_forwarding_prep_0 + 14
5 NetIncome 0x000358da -[NetIncomeViewController viewDidLoad] + 954
6 UIKit 0x003d1318 -[UIViewController loadViewIfRequired] + 696
7 UIKit 0x003f6b15 -[UINavigationController _layoutViewController:] + 39
8 UIKit 0x003f702b -[UINavigationController _updateScrollViewFromViewController:toViewController:] + 235
9 UIKit 0x003f7123 -[UINavigationController _startTransition:fromViewController:toViewController:] + 78
10 UIKit 0x003f809c -[UINavigationController _startDeferredTransitionIfNeeded:] + 645
11 UIKit 0x003f8cb9 -[UINavigationController __viewWillLayoutSubviews] + 57
12 UIKit 0x00532181 -[UILayoutContainerView layoutSubviews] + 213
13 UIKit 0x00328267 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 355
14 libobjc.A.dylib 0x01ad081f -[NSObject performSelector:withObject:] + 70
15 QuartzCore 0x001972ea -[CALayer layoutSublayers] + 148
16 QuartzCore 0x0018b0d4 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
17 QuartzCore 0x0018af40 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 26
18 QuartzCore 0x000f2ae6 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 294
19 QuartzCore 0x000f3e71 _ZN2CA11Transaction6commitEv + 393
20 QuartzCore 0x001b0430 +[CATransaction flush] + 52
21 UIKit 0x002d9dc9 _afterCACommitHandler + 131
22 CoreFoundation 0x01e974ce __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
23 CoreFoundation 0x01e9741f __CFRunLoopDoObservers + 399
24 CoreFoundation 0x01e75344 __CFRunLoopRun + 1076
25 CoreFoundation 0x01e74ac3 CFRunLoopRunSpecific + 467
26 CoreFoundation 0x01e748db CFRunLoopRunInMode + 123
27 GraphicsServices 0x0351e9e2 GSEventRunModal + 192
28 GraphicsServices 0x0351e809 GSEventRun + 104
29 UIKit 0x002bdd3b UIApplicationMain + 1225
30 NetIncome 0x00002b3d main + 141
31 libdyld.dylib 0x031c070d start + 1
32 ??? 0x00000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
The lines of code my app crashes the first time (the last line is the one):
//Get or set and get the gross income
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDecimalNumber *grossIncome = [defaults objectForKey:#"grossincome"];
if (!grossIncome) {
[defaults setObject:[NSDecimalNumber zero] forKey:#"grossincome"];
[defaults synchronize];
grossIncome = (NSDecimalNumber *)[defaults objectForKey:#"grossincome"];
}
self.incomeValueTextField.enabled = NO;
self.incomeValueTextField.delegate = self;
self.incomeValueTextField.keyboardType = UIKeyboardTypeDecimalPad;
self.incomeValueTextField.text = [grossIncome getLocalizedCurrencyString];
And my complete category:
#import "NSDecimalNumber+Currency.h"
#import "Singletons.h"
#implementation NSDecimalNumber (Currency)
- (NSString *) getLocalizedCurrencyString
{
NSNumberFormatter *numberFormatter = [[Singletons sharedManager] numberFormatter];
NSString *numberString = [numberFormatter stringFromNumber:self];
return numberString;
}
- (NSString *) getLocalizedCurrencyStringWithDigits:(int)digits
{
if(digits == 2){
return [self getLocalizedCurrencyString];
}
NSNumberFormatter *numberFormatter;
if (digits == 0){
numberFormatter =[[Singletons sharedManager] numberFormatterNoDigits];
} else {
numberFormatter =[[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
[numberFormatter setLocale:[NSLocale currentLocale]];
[numberFormatter setMinimumFractionDigits:digits];
[numberFormatter setMaximumFractionDigits:digits];
}
NSString *numberString = [numberFormatter stringFromNumber:self];
return numberString;
}
+ (NSDecimalNumber *) getUnLocalizedDecimalNumberWithString:(NSString *)currencyString
{
NSNumberFormatter *numberFormatter = [[Singletons sharedManager] numberFormatter];
NSNumber *formatedCurrency = [numberFormatter numberFromString:currencyString];
BOOL isDecimal = formatedCurrency != nil;
if(isDecimal){
return [NSDecimalNumber decimalNumberWithDecimal:[formatedCurrency decimalValue]];
} else {
return [NSDecimalNumber zero];
}
}
- (NSDecimalNumber *)abs {
if ([self compare:[NSDecimalNumber zero]] == NSOrderedAscending) {
// Number is negative. Multiply by -1
NSDecimalNumber * negativeOne = [NSDecimalNumber decimalNumberWithMantissa:1
exponent:0
isNegative:YES];
return [self decimalNumberByMultiplyingBy:negativeOne];
} else {
return self;
}
}
Yesterday you have been warned about subclassing/categories on class clusters, now you see why. (Okay, actually it's more or a problem with unexpected behaviour of NSUserDefaults, but it's related ^^)
Your problem is that the object you get from NSUserDefaults is not a NSDecimalNumber, because NSDecimalNumbers are not plist values that can be saved in NSUserDefaults. But NSDecimalNumber is a subclass of NSNumber, which can be saved in NSUserDefaults, so NSUserDefaults will only save the "NSNumber part" of the NSDecimalNumber, basically it converts it to a NSNumber. Through this process it loses its precision and it's class.
When you get the object from NSUserDefaults you will actually get an instance of NSNumber. And your category does not exist on NSNumber.
I added some debug log to your code and ran it for you:
// Wrong!
NSDecimalNumber *decimalNumber = [NSDecimalNumber decimalNumberWithString:#"1.23456789123456789"];
NSLog(#"%# - %#", decimalNumber, NSStringFromClass([decimalNumber class]));
[[NSUserDefaults standardUserDefaults] setObject:decimalNumber forKey:#"___number"];
NSDecimalNumber *objectFromUserDefaults = [[NSUserDefaults standardUserDefaults] objectForKey:#"___number"];
NSLog(#"%# - %#", objectFromUserDefaults, NSStringFromClass([objectFromUserDefaults class]));
Which yields this result:
xxx[98912:70b] 1.23456789123456789 - NSDecimalNumber
xxx[98912:70b] 1.234567891234568 - __NSCFNumber
As you can see the returned object is an instance of __NSCFNumber
Here is the correct way:
// Correct
NSDecimalNumber *decimalNumber = [NSDecimalNumber decimalNumberWithString:#"1.23456789123456789"];
NSLog(#"%# - %#", decimalNumber, NSStringFromClass([decimalNumber class]));
NSData *archivedDecimalNumber = [NSKeyedArchiver archivedDataWithRootObject:decimalNumber];
[[NSUserDefaults standardUserDefaults] setObject:archivedDecimalNumber forKey:#"___archivedNumber"];
NSData *dataFromUserDefaults = [[NSUserDefaults standardUserDefaults] objectForKey:#"___archivedNumber"];
NSDecimalNumber *decimalNumberFromUserDefaults = [NSKeyedUnarchiver unarchiveObjectWithData:dataFromUserDefaults];
NSLog(#"%# - %#", decimalNumberFromUserDefaults, NSStringFromClass([decimalNumberFromUserDefaults class]));
which yields:
xxx[98912:70b] 1.23456789123456789 - NSDecimalNumber
xxx[98912:70b] 1.23456789123456789 - NSDecimalNumber
as expected.
BUT you should still get rid of that NSDecimalNumber category. Just put that code into it's own class. Call it ZHNumberFormatter and do your formatting in there.
NSNumberFormatters take their time during creation, you don't want to create them for every single conversion.
Reset your simulator and try to run the app.
iOS Simulator --> Reset content and settings.
User NSKeyedArchiver and NSKeyedUnarchiver to store the object in user defaults.
Try to use below code its working fine.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDecimalNumber *grossIncome = [defaults objectForKey:#"grossincome"];
if (!grossIncome) {
NSDecimalNumber *decNum = [[NSDecimalNumber alloc] initWithDouble:0.0f];
NSData *myEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:decNum];
[defaults setObject:myEncodedObject forKey:#"grossincome"];
[defaults synchronize];
NSData *myDecodedObject = [defaults objectForKey:#"grossincome"];
grossIncome = (NSDecimalNumber*)[NSKeyedUnarchiver unarchiveObjectWithData:myDecodedObject];
}
[grossIncome getLocalizedCurrencyString];
You probably still refer to the category somewhere.
You should create an exception Breakpoint. (look for "create exception Breakpoint" in the help menu)
This will stop you on the guilty line of code!