views:

39

answers:

2

I'm having trouble with my update logic. I need to include a file in the app bundle which contains specific update data. When the app discovers this file, it checks to see if it's a first install (no update needed) or a previous install (apply update). Whatever the outcome, the update file needs to be deleted, so it's not found again, otherwise the app will apply the update each time the app is run, which is bad.

Since it's impossible to remove anything from [[NSBundle mainBundle], I need to figure out the best way to do this. If I could include the update file inside of the Application's Library path, it would be much simpler.

The reason I need this is because on first load, the application creates a file of user data and stores it inside the Library path. From then on, the application loads that user file. In this case, the file that was created has outdated data. I created a new file with updated data to apply to the user's main file.

Can anyone help me through this? here's what i have:

if ([self checkUpdateFile] == YES) {
    [self applyUpdate];
}

-(BOOL)checkUpdateFile {
NSString *updateFilePath = [[NSBundle mainBundle]pathForResource:@"updateData"
        ofType:@"dat" inDirectory:@"update"];
BOOL updateFileExists = [[NSFileManager defaultManager]
        fileExistsAtPath: updateFilePath];
NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
        NSUserDomainMask, YES) objectAtIndex:0];
NSString *programDataPath = [libraryPath stringByAppendingPathComponent: 
        @"programData.dat"];
BOOL programFileExists = [[NSFileManager defaultManager]fileExistsAtPath: 
        programDataPath];
if (programFileExists == YES && updateFileExists == YES) {
    NSLog(@"Update File is present, and so is a data file, so this is a previous install");
    return YES;
} else {
    NSLog(@"This is not an upgradeable version.");
    if (updateFileExists == YES) {
        NSLog(@"The update file is here but this is the first install.");
        [[NSFileManager defaultManager]removeItemAtPath: updateFilePath 
                        error:NULL];
        BOOL doesFileStillExist = [[NSFileManager defaultManager] 
                        fileExistsAtPath:updateFilePath];
        if (doesFileStillExist == YES) {
            NSLog(@"File still exists");
        } else {
            NSLog(@"File was deleted.");
        }
    }
    return NO;
}
}

-(void)applyUpdate {
NSLog(@"Applying Update");
NSString *filePath = [[NSBundle mainBundle]pathForResource:@"updateData" 
        ofType:@"dat" inDirectory:@"update"];
NSData *programData = [[NSData alloc] initWithContentsOfFile:filePath];
NSKeyedUnarchiver *decoder = [[NSKeyedUnarchiver alloc] 
        initForReadingWithData:programData];
NSMutableArray *characterList = [[decoder 
        decodeObjectForKey:@"characterList"]retain];
int i = 0;
for (Character *player in characterList) {
    NSMutableArray *movesList = player.moves;
    Character *existingCharacter = [self.dataController.characterList 
                objectAtIndex:i];
    NSLog(@"Found Character: %@",existingCharacter.name);
    existingCharacter.moves = movesList;
    i++;
}

BOOL doesFileStillExist = [[NSFileManager defaultManager] 
         fileExistsAtPath:filePath];
if (doesFileStillExist == YES) {
    NSLog(@"File still exists");
} else {
    NSLog(@"File was deleted.");
}
[self writeDataToDisk];
[characterList release];
[decoder release];
[programData release];

}
A: 

You answered your own question; you can't delete files inside the application bundle. Treat the whole bundle like a read-only directory.

You'll have to clarify exactly why you're trying to do this as I don't understand it from your description. Try explaining it at a high level (a "functional" description) -- what do you want to happen and why? (Not how you want something to happen, which is a low-level or "non-functional" description.)

Shaggy Frog
User starts app first time, and a data file is created programatically, and then written to disk. On subsequent launches, the data file is reinitialized from the disk. Over time, that data gets obsoleted, but still has important bits in it. In order to maintain the user's data and not destroy it/start from scratch, I want to "append" the user's data file with some new, fresh data. I opted to just create a BOOL in the userDefaults showing that an update has been applied, and ignore the update file in my mainBundle. I'd rather delete the updateFile, but oh well.
JustinXXVII
+1  A: 

If app is running on first launch, make your update. As the update data is part of your main bundle, you will not be able to delete the file

After you have made the update, write a BOOL entry to a plist file (something like appIsUpdated).

On subsequent launches, check for existence of the plist file and the value of appIsUpdated. If !appIsUpdated, update the app.

TomH