Первое обновление приложения, потеря данных пользователя (хранилась в каталоге Documents)
Мое первое обновление для приложения прошло вчера вечером, и я получил жалобу на то, что обновление вызвало исчезновение пользовательских данных (некоторые из них). Я смог воспроизвести проблему, но не могу понять, почему.
В папке "Документы" я сохранил один ключевой файл, который сообщает мне "название" всех файлов пользователя и их файлов (полный путь). Затем все пользовательские файлы также находятся в каталоге Documents.
Когда происходит обновление, файл ключей все еще существует (по крайней мере, я думаю, это потому, что данные отображаются на первом экране приложения - приложения полностью завершают работу и перезапускают после обновления, верно?), но когда пользователь пытается перейти к фактическим файлам, данных нет, и любые новые данные, которые пользователь вводит, никогда не сохраняются.
Он действует точно так же, как при отладке, когда я случайно использовал недопустимое имя файла (с неправильными символами в нем) - он никогда не сохранялся. Но с обновлением эти файлы были сохранены правильно в старой версии, но как-то не работают в новой версии.
Это мое первое приложение и мое первое обновление, и я здесь совсем не понимаю. Я вытащил приложение из продажи на данный момент (не знал, что вы не можете просто вернуться к старой версии! Yikes!) И глубоко оценит любые идеи о том, где/как искать проблему и как писать ХОРОШЕЕ обновление, которое не потеряет данные. (Пока все, что я нашел, это "сохранить данные в каталоге" Документы ", что я уже делал.)
У меня есть оригинальное приложение, сохраненное в его собственном проекте, и я могу вернуться и снова работать с этим. Я скопировал весь этот каталог, когда начал работать над обновлением, и я задаюсь вопросом, может ли это как-то быть проблемой? Я изменил имя каталога, в котором хранятся все файлы XCode, и использовал функцию Project > Rename. Может ли это иметь такой эффект?
Приложение (как оригинал, так и обновление) работает на 4.2 и выше, если это имеет значение.
Решение:
Я считаю, что я понял эту проблему. Как я уже говорил в начале моего вопроса, я сохранял ПОЛНУЮ ПУТЬ файлов пользователя в моих файлах ключей. По-видимому, после обновления не гарантируется, что полный путь не будет таким же (я уверен, что это где-то где-то зарегистрировано, но я не сталкивался с ним).
Итак, пользовательские файлы HAD были перенесены в новый каталог Documents, но я искал их по старому абсолютному пути, то есть не в моей песочнице.
Исправлено, поместив цикл в приложение didFinishLaunching, чтобы вытащить нарушительный файл файловых путей (THAT, я всегда искал локально, и он все еще работал) и отрубал их только до файлаNAMES. Путь к документам должен быть найден и добавлен программно всякий раз, когда выполняются операции с файлами.
Для меня это было действительно полезно для меня, что нет способа вернуться к предыдущему двоичному файлу в магазине, потому что повторная установка исходной версии не устранила бы проблему пользователя, но я бы поверила, что она, по крайней мере, изначально. Я бы хотел, чтобы был способ отклонить ОБНОВЛЕНИЯ, но все же разрешил новые покупки (так как проблема не повлияла на новые покупки). Вероятно, это не достаточно распространенная ситуация, чтобы гарантировать это.
Ответы
Ответ 1
Просто пролить немного света на это для интернет-прохожих. Да, ОП ответил на свой вопрос в самом конце. Вы никогда не должны хранить абсолютные URL-адреса для файлов в каталоге документов, и это может привести к потере данных. Это связано с тем, что при обновлении приложения, изменяя свою версию # в файле .plist, iOS создает новый каталог для этого приложения с другим шестнадцатеричным именем. Теперь ваш абсолютный URL-адрес ссылается на неправильное местоположение и не вернет правильный файл.
Вы можете увидеть это на своем собственном компьютере, прежде чем развертывать его на устройстве, перейдя к
~/Library/Поддержка приложений/Симулятор iPhone/* ios_version */Приложения/
Там вы увидите папки с именами вроде:
6AA4B05C-8A38-4469-B7BE-5EA7E9712510
CB43C5F3-D720-49C3-87D4-EBE93FFD428B
Внутри этих папок будет стандартный макет файловой системы для приложений iOS. то есть.
Документы
Библиотека
TMP
YourApp.app
Переходя по всему URL-адресу, вы увидите что-то вроде
~/Library/Поддержка приложений /iPhone Simulator/* ios_version */Приложения/6AA4B05C-8A38-4469-B7BE-5EA7E9712510/Documents/MyVeryImportantUserData.txt
Однако при обновлении приложения новый URL-адрес приложения будет выглядеть следующим образом:
~/Library/Поддержка приложений /iPhone Simulator/* ios_version */Приложения/CB43C5F3-D720-49C3-87D4-EBE93FFD428B/Documents/MyVeryImportantUserData.txt
который пуст.
Вместо этого вы всегда должны делать динамическую ссылку, сохраняя только путь к файлу после того, как вы получили префикс пути к файлу каталога документов.
/**
Returns the path to the application Documents directory.
*/
- (NSString *)applicationDocumentsDirectory {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}
На исходный плакат вы могли бы сохранить ваши потерянные данные пользователей, выпустив новое обновление, в котором вы изменили свой код, чтобы получить абсолютный URL-адрес и обрезать все через часть документов в строке. Затем вы можете префикс пути к файлу с соответствующим URL-адресом каталога, и приложение обнаружило бы данные.
Ответ 2
Оба вопросника и первый ответ были полезны для выяснения того, что именно происходит.
Поэтому, основываясь на своих наблюдениях, я понял, что было (что, кажется,) переименование папок в пути, ведущем к папке "Документы". Это привело меня к решению, в котором я сохраняю только файлы имен файлов и создаю класс утилиты для захвата строки fullPath current, которая была сохранена и теперь хранится в текущая папка "Документы" после обновления приложения:
#import "StringUtils.h"
@implementation StringUtils
+ (NSString *)getFullDocumentUrl:(NSString *)fileName
{
return [NSString stringWithFormat:@"%@/%@",[self applicationDocumentsDirectory],fileName];
}
+ (NSString *)applicationDocumentsDirectory
{
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}
@end
Ответ 3
Я столкнулся с той же проблемой. Ниже приведен пример кода для исправления ваших имен файлов путем итерации через файлы в каталоге документов и замены информации о пути файла, оставляя имена файлов. Перед выполнением последней строки, чтобы изменить имена файлов, я рекомендовал бы использовать NSLog, чтобы убедиться, что это именно то, что вы хотите в своем обновленном имени.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory
NSFileManager *fm = [NSFileManager defaultManager];
NSArray *filenames = [fm contentsOfDirectoryAtPath:documentsPath error:nil];
//Match on the filepath leading up to docs directory
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^/\\S*Documents/"
options:NSRegularExpressionCaseInsensitive
error:nil];
for (NSString *fileName in filenames)
{
NSRange fullLength = NSMakeRange(0, [fileName length]);
//swap out the prepended directory structure with an empty string
NSString *updatedFileName = [regex stringByReplacingMatchesInString:fileName
options:0
range:fullLength
withTemplate:@""];
NSString *currentName = [NSString stringWithFormat:@"%@/%@",documentsPath,fileName];
NSString *updatedName = [NSString stringWithFormat:@"%@/%@",documentsPath,updatedFileName];
[fm moveItemAtPath:currentName toPath:updatedName error:nil];
}