Files are no longer readable after updating applic

2019-08-09 01:34发布

问题:

I have been working on an Enterprise distributed application for the iPad for about a year. We have released 5 production builds in that time and never experienced any issues. Every time our users have installed the new build over the old version, and our Core Data migrations always worked fine. UNTIL we added video recording to the application.

We had been storing 'Media' in the Core Data Externally Managed data type. This was working fine until we started to allow the user to create large videos. So we then discovered that Core Data migrations trash any file that is over ~5mb. At this point we rolled our own File Management scheme. This worked out perfectly fine, we wrote our own manual migration of the files out of Core Data and into our own scheme. This was released without issue.

THEN, when it came time to roll out our NEXT set of features, suddenly a problem popped up. There were never any issues when building from Xcode... But, after redeploying using Enterprise Deployment, any of the files that were written to the filesystem in the previous build were suddenly unreadable. If a device is plugged into XCode, the files are clearly visible in the Organizer. However NSFileManager/NSFileHandle/NSData can not find the files. They always report that they experience:

error: {
    NSFilePath = "/var/mobile/Applications/3CFB07B3-D17F-45D7-A233-4E56930D794C/Documents/ep_binary_data/9465C282-7ED2-428E-B7D3-545BCFE4DFC5";
    NSUnderlyingError = "Error Domain=NSPOSIXErrorDomain Code=2 \"The operation couldn\U2019t be completed. No such file or directory\"";
}

Like I said, I can verify that the file DOES ACTUALLY EXIST at that path using the XCode Organizer. Any help would be greatly appreciated. I have been banging my head off the desk all day trying to figure this out.

The code used to read looks like:

NSError *err = nil;
NSData *data = [[NSData alloc] initWithContentsOfFile:self.thumbnail_url 
                                              options:NSDataReadingMappedIfSafe 
                                                error:&err];
if (err != nil) logger(@"error: %@",[err userInfo]);

And to write:

NSError *error = nil;
[thumbnail_ep_managed writeToFile:filePath options:NSDataWritingAtomic error:&error];
if(error != nil)
{
    NSLog(@"error writing file to path: %@\nerror: %@",filePath,[[error userInfo]description]);
}

I'm stumped

回答1:

I found the solution with the help of some Goons at SomethingAwful. The issue was that I was storing the FULL path, as in including the documents directory. This is a mistake on an iOS device. You cannot guarantee that after an upgrade, the bundle path will still be the same.

Sometimes the bundle identifier (the name of the directory the app is installed in), which is a hash, is changed when upgrading an application. So if you store the full path, and upgrade may brake the stored paths. The solution is to only persist a relative path, starting from the documents directory.

Then when you start the application, cache the documents directory, and append your persistent relative paths.

So from my original path:

/var/mobile/Applications/3CFB07B3-D17F-45D7-A233-4E56930D794C/Documents/ep_binary_data/9465C282-7ED2-428E-B7D3-545BCFE4DFC5

This part can change:

3CFB07B3-D17F-45D7-A233-4E56930D794C

So I should only be storing:

ep_binary_data/9465C282-7ED2-428E-B7D3-545BCFE4DFC5

And grab the:

/var/mobile/Applications/3CFB07B3-D17F-45D7-A233-4E56930D794C/Documents/

part on application start.

Voila, the files keep working. :)