Search code examples
iosnsfilemanagerfoundation

Resource File Not Found after App Upgrade?


My app is bundled with two preinstalled videos, and the user can purchase more through in-app-purchase.

Each video episode is an objective-C object with an ivar called _videoFilePath (property NSString* videoFilePath)

When a video finished downloading, the file path is appropriately set. For preinstalled episodes, it is set once at startup with code like this:

NSString* fileName = [NSString stringWithFormat:@"Chapter_%03d", _episodeNumber];
self.videoFilePath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"m4v"];

(Episode metadata is initialized from a bundled .plist on the first run, and a copy of that .plist is saved in /Documents and used on subsequent runs. This is because the metadata is read/write, but bundled resources are read-only)

I've noticed that some users can play the preinstalled videos after upgrading my app. I am currently investigating this, so I deleted the app from the Device, installed version 1.0 (from Xcode->Run), Archived version 1.1 as AdHoc and installed that on top. As expected, the preinstalled episodes won't play.

So this time I built/run version 1.1 from Xcode, on top of the AdHoc install, with some breakpoints enabled.

Purchased (downloaded) episodes are saved to the cache, so the presence of a valid file path is not enough to guarantee playback (might be deleted by the system). So I use NSFileMananger to check if the file exists before attempting playback, with code like this:

if (_videoFilePath) {
        // Video File Path is Set...

        if ([[NSFileManager defaultManager] fileExistsAtPath:_videoFilePath]) {
            // ...and file exists in system; 
            // Can Play:

            return YES;                
        }
        else{
            // ...but file has been deleted, possibly as a result of a 
            // restore from iTunes backup; 
            // Can Not Play:

            return NO;
        }
    }

The breakpoints revealed that the fileExistsAtPath: test fails; However the console shows the value of _videoFilePath as:

/var/mobile/Applications/CEAA80EF-A85F-4C60-929D-9BA18E8D1702/[App Name]/Chapter_001.m4v

So, what gives?

Note: Deleting the app and reinstalling version 1.1 seems to fix the problem. The bug only manifests itself when you upgrade to 1.1 on top of 1.0.

ADDENDUM

After a second of thought (writing things down does help), I think I've figured it out. The file path for the resource is obtained on the first run of version 1.0, and saved in the /Documents folder with the rest of the metadata. On upgrade, I assume the 'Random numbers, letters and hyphens' part of the app's path changes to something else, and thus the 'hard-coded' path from version 1.0 becomes a broken URL. Must NSLog the full path on both v1.0 and v1.1 to confirm this, but I think I got it. Answers and comments are still welcome.


Solution

  • So, as I realized after some thought, the full path for bundled resources seems to change slightly on each upgrade of the app; Specifically, the "Long, autogenerated random string of numbers and letter" intermediate directory. My mistake was in saving (i.e., hard-coding) the path on the first install, and using that value even after app upgrades. I solved it by not caching the path and instead using

    -pathForResource:ofType:
    

    each time.