NSKeyedUnarchiver - how to prevent a crash
Asked Answered
C

2

8

I guess this is very obvious, but I have a question about loading data. If have a file called library.dat which stores all kind of information about objects in the app. It's set up all nicely (in terms of the initWithCoder and encodeWithCoder methods etc.), but I was just wondering what happens if the library.dat ever gets corrupted. I corrupted it a bit myself and the app will then crash. Is there any way to prevent a crash? Can I test a file before loading it? Here is the bit which can potentially be very fatal:

    -(void)loadLibraryDat {

    NSLog(@"loadLibraryDat...");
    NSString *filePath = [[self documentsDirectory] stringByAppendingPathComponent:@"library.dat"];

    // if the app crashes here, there is no way for the user to get the app running- except by deleting and re-installing it...
    self.libraryDat = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];



}

I had a look at *NSInvalidUnarchiveOperationException but have no idea how I should implement this in my code. I'd be grateful for any examples. Thanks in advance!

Coverley answered 26/9, 2011 at 15:53 Comment(0)
E
14

You can wrap the unarchive call with @try{}@catch{}@finally. This is described in Apple docs here: http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/ObjectiveC/Chapters/ocExceptionHandling.html

@try {
    self.libraryDat = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
} @catch ( NSInvalidUnarchiveOperationException *ex ) {
    //do whatever you need to in case of a crash
} @finally {
    //this will always get called even if there is an exception
}
Edmundson answered 26/9, 2011 at 16:3 Comment(2)
Thanks a lot for confirming that this is the official way to handle this.Coverley
NSInvalidUnarchiveOperationException is a string, not a class of Exception. So I think you have to catch NSException, then check against its name...?Othelia
E
4

Have you tried 'try/catch' blocks? Something like this:

@try {
    self.libraryDat = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
}
@catch (NSException* exception) {
    NSLog(@"provide some logs here");
    // delete corrupted archive
    // initialize libraryDat from scratch
}
Elianore answered 26/9, 2011 at 16:2 Comment(6)
Thanks! I'm fairly new to this and people always warned against 'try/catch' blocks. Sounds very reasonable in this case, though. I guess there is no other way but to work with blocks, right?Coverley
I think there is no other simple solutions. Unfortunately.Elianore
Just tried this, but xCode tells me that "Unknown type name 'NSInvalidUnarchiveOperationException'" -- do I have to define it previously?Coverley
Or should this be @catch(NSException *exception) ?Coverley
Have you imported NSKeyedArchiver.h?Elianore
NSInvalidUnarchiveOperationException is not an exception, it's a string constant. It should be @catch (NSException* exception)Elena

© 2022 - 2024 — McMap. All rights reserved.