views:

24

answers:

2

Currently, my Iphone application is not released yet. When I worked with the simulator/device and I modify my application to add more cache into the encodeWithCode: and initWithCoder: . The problem is that when the application is loaded, I tried to use some of the encoded object which is not existing before. For example:

In the previous application version (e.g 1.2), I have this encode:

- (void)encodeWithCoder:(NSCoder*)coder {
    [coder encodeObject:myArray forKey:NCITEMTABLE_ARCHIVE_HOME_ITEMS_KEY];
}

But with new version (e.g 1.3), I use this init:

- (id)initWithCoder:(NSCoder*)coder {
    if (self = [super initWithCoder:coder]) {
        myArray = [[coder decodeObjectForKey:NCITEMTABLE_ARCHIVE_HOME_ITEMS_KEY] retain];
        myArray2 = [[coder decodeObjectForKey:NCITEMTABLE_ARCHIVE_HOME_ITEMS_2_KEY] retain];
    }
    return self;
}

and then the application will crash because it cannot find myArray2.

In the simulator or testing, I can just delete the old version and install from fresh. However, I am afraid that when it is released, I cannot tell my user to delete the old app and install the new fresh one. Have anyone experienced about this problem?

A: 

I tried to use try catch to get the exception. It may not be the best answer but it works now . The problem is that it may have low performance when it has to do try catch exception, which is not recommended by Apple

  if (archive) {
        @try {
            [self unarchiveInitializingWithData:archive];
        }
        @catch (NSException * e) {
            NCLog (@"Cannot unarchive");
            [self normalInitializing];
        }
    } else {
        NCLog (@"Normal init");
        // normal init
        [self normalInitializing];
    }  
vodkhang
+1  A: 

In your initWithCoder you should be able to just call containsValueForKey to see if the key exists before trying to call decodeObjectForKey

superfell
So, if it doesn't contain and you really need that attribute, you return nil?. I try to return nil in that case but it still crashes
vodkhang
and the containsValueForKey cannot check for the case: I encode an object but decodeInt later
vodkhang
another case I want to deal with is that: I have a navigation stack, VC A -> VC B -> VC C. If VC C fails to initWithCoder, I still want to init VC A and VC B so that user don't have to go from beginning again
vodkhang
the containsValueForKey will let you know that you need to "upgrade" to your new state from their oldstate, only you can work out the particulars of how to do that. (setting things to nil, or to empty arrays etc)
superfell