Not sure how to handle “Terminating app due to unc

2019-08-17 05:55发布

问题:

I'm working on creating an app that uses a class I created myself, Entry, to store specific data in an array. However, I keep running into this error when I try to access one of the values stored in an Entry object. Every time I prompt the user to create one of these objects, it is added to "rawArray," which is in turn stored into [NSUserDefaults standardUserDefaults]. At these lines of code, the program crashes:

Entry *currEntry = [[[NSUserDefaults standardUserDefaults] arrayForKey:@"rawArray"] objectAtIndex:section];
NSLog(@"date: %@", [currEntry getDate]);

I'm only trying to pull the array element that corresponds to the current UITableView section, and then NSLog the "date" variable stored in it. Here is the getDate method from the Entry class:

-(NSString *)getDate{
   return date;
}

The date object itself is just another NSString in the Entry class, which is set in the class's init. If anyone can help me sort through this problem, I'd be incredibly thankful.

Here is the full crash log:

2012-04-24 16:31:32.545 Know[7278:f803] -[__NSCFString getDate]: unrecognized selector sent to instance 0x68598f0
2012-04-24 16:31:32.546 Know[7278:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString getDate]: unrecognized selector sent to instance 0x68598f0'
*** First throw call stack:
(0x13cb052 0x155cd0a 0x13ccced 0x1331f00 0x1331ce2 0xa930 0xb85c9 0xb8480 0x1fc849 0x1ff722 0xaf7c7 0xaf2c1 0xb228c 0xb6783 0x61301 0x13cce72 0x1d7592d 0x1d7f827 0x1d05fa7 0x1d07ea6 0x1d9330c 0x33530 0x139f9ce 0x1336670 0x13024f6 0x1301db4 0x1301ccb 0x12b4879 0x12b493e 0x22a9b 0x1d98 0x1cf5)
terminate called throwing an exception

After I switched over to using NSKeyedArchiver/Unarchiver, I still ran into the same problem. Here are my new retrieve and save methods:

-(void)saveToUserDefaults:(NSMutableArray *)array{
    NSData *myEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:array];
    [[NSUserDefaults standardUserDefaults] setObject:myEncodedObject forKey:@"rawArray"];
}

-(NSMutableArray *)loadFromUserDefaults{
    NSData *myDecodedObject = [[NSUserDefaults standardUserDefaults] objectForKey:@"rawArray"];
    NSMutableArray *decodedArray =[NSKeyedUnarchiver unarchiveObjectWithData: myDecodedObject];
    return decodedArray;
}

Here are the new lines of code that crash the program:

Entry *currEntry = [[self loadFromUserDefaults] objectAtIndex:section];
NSLog(@"date: %@", [currEntry getDate]);

And here is the updated crash log:

2012-04-24 17:43:36.853 Know[10314:f803] -[__NSCFString getDate]: unrecognized selector sent to instance 0x6acc260
2012-04-24 17:43:36.904 Know[10314:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString getDate]: unrecognized selector sent to instance 0x6acc260'
*** First throw call stack:
(0x13ce052 0x155fd0a 0x13cfced 0x1334f00 0x1334ce2 0xb710 0xbb5c9 0xbb480 0x1ff849 0x202722 0xb27c7 0xb22c1 0xb528c 0xb9783 0x64301 0x13cfe72 0x1d7892d 0x1d82827 0x1d08fa7 0x1d0aea6 0x1d9630c 0x36530 0x13a29ce 0x1339670 0x13054f6 0x1304db4 0x1304ccb 0x12b7879 0x12b793e 0x25a9b 0x2a18 0x2975)
terminate called throwing an exception

回答1:

I think that the proble is that you are storing an array of custom objects via NSUserDefaults. Maybe you should check this article about this: How to Save array of custom class in NSUserDefaults or this question.

EDIT


Did you add the methods encodeWithCoder and initWithCoder. Maybe the problem is in its implementation.



回答2:

What is exactly what makes your app crash from those lines? There are 3 potential cases:

  1. Accessing item indexed by @"rawArray" from standardUserDefaults.
  2. Accessing the section index from that array.
  3. Accessing the entry date.

I would bet that the problem is related with your Entry class and the NSUserDefaults. To store an object to a userDefaults, it has to conform the NSCoding protocol (NSArray and NSDictionary already do and base types are also possible to be used with their respective methods).

But I have to say that if this is the problem, your application would have crashed when you stored the Entries too... so I really don't know exactly what is happening.

Just try to be a little bit clearer about which method makes your app crash. Good luck!



回答3:

Use NSKeyedArchiver first (before storing them into NSUserDefaults)

like this:

save:

NSData *dataForNSUserDefaults = [NSKeyedArchiver archivedDataWithRootObject:yourEntry];
[[NSUserDefaults standardUserDefaults] setObject:dataForNSUserDefaults forKey:@"yourKey"];

load:

NSData *archivedData = [[NSUserDefaults standardUserDefaults] objectForKey:@"yourKey"];
Entry *yourEntry = [NSKeyedUnarchiver unarchiveObjectWithData:arrayAsData];


回答4:

The error message is saying that the thing you think is an Entry is actually a string. My first guess is that you try to save a custom object type which is being converted to a string description of the type. Try logging the object to see for sure:

NSLog(@"Entry: %@", currEntry);

Look at the NSUserDefaults documentation about data types to see what it supports.



回答5:

NSUserDefaults can't store instances of custom classes. It can only store simple things like strings, booleans, and dictionaries.

That's why you're getting [__NSCFString getDate]: unrecognized selector sent to instance. __NSCFString is one of Apple's private classes for NSString. Basically it's saying that your call to NSUserDefaults returned an NSString, and NSString doesn't have a method called getDate.

You need to serialize and deserialize your data, so in order to store your objects in NSUserDefaults, you'd need to first convert your object into a dictionary representation of all of the values. Then when you want to convert your data back into an object, you do the reverse. Key-Value coding is usually helpful.

By the way, getDate is not Objective-C method naming compliant. If you have a synthesized property on a class called date, you should have date be the name of the property, and then synthesize it using @synthesize date = _date;. @synthesize will write your getter and setter (accessor and mutator) methods for you, so you can just call setData: or data and it'll figure out what to do. If you're using ARC or key-value coding, this is especially important because in some cases, the runtime will assume that you're following their guidelines.

Finally, it is highly advisable to only use NSUserDefaults for what it's meant for - defaults. This would include settings and other non-confidential information. Performance isn't great if you start making lots of changes and requests. Use a plist you save to the Documents directory, SQLite, or Core Data.