Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/104.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/115.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 第一次应用程序更新,用户数据丢失(存储在文档目录中)_Ios_File Io_Filesystems - Fatal编程技术网

Ios 第一次应用程序更新,用户数据丢失(存储在文档目录中)

Ios 第一次应用程序更新,用户数据丢失(存储在文档目录中),ios,file-io,filesystems,Ios,File Io,Filesystems,我的第一个应用程序更新昨晚刚刚上线,我接到一个投诉,说更新导致用户创建的数据(其中一些)消失了。我已经能够重现这个问题,但不知道为什么 在Documents目录中,我保存了一个关键文件,它告诉我所有用户文件的“标题”及其文件名(完整路径)。然后,所有用户的文件也都在Documents目录中 当更新发生时,密钥文件仍然存在(至少,我认为这是因为数据显示在应用程序的第一个屏幕上-更新后应用程序确实完全退出并重新启动,对吗?),但当用户尝试导航到实际文件时,没有数据,并且用户键入的任何新数据都不会保存

我的第一个应用程序更新昨晚刚刚上线,我接到一个投诉,说更新导致用户创建的数据(其中一些)消失了。我已经能够重现这个问题,但不知道为什么

在Documents目录中,我保存了一个关键文件,它告诉我所有用户文件的“标题”及其文件名(完整路径)。然后,所有用户的文件也都在Documents目录中

当更新发生时,密钥文件仍然存在(至少,我认为这是因为数据显示在应用程序的第一个屏幕上-更新后应用程序确实完全退出并重新启动,对吗?),但当用户尝试导航到实际文件时,没有数据,并且用户键入的任何新数据都不会保存

它的行为与调试时完全相同,当时我无意中使用了无效的文件名(其中包含不正确的字符)-它从未保存。但随着更新,这些文件在旧版本中已正确保存,但在新版本中却以某种方式失败

这是我的第一个应用程序,也是我的第一次更新,我在这里完全不知所措。我已经暂时停止销售该应用程序(不知道你不能简单地恢复到旧版本!yikes!),如果你能提供任何关于在哪里/如何查找问题以及如何编写一个不会丢失数据的良好更新的想法,我将不胜感激。(到目前为止,我只找到了“在文档目录中保存数据”,这是我已经在做的事情。)

我确实在自己的项目中保存了最初的应用程序,我可以再回去工作。当我开始更新时,我复制了整个目录,我想知道这是否是问题所在?我确实更改了保存所有XCode文件的目录的名称,并使用了Project>Rename函数。那会有这种效果吗

如果有必要,该应用程序(包括原始应用程序和更新应用程序)正在4.2及以上版本上运行

决议:

我相信我已经解决了这个问题。正如我在问题开始时所说,我正在将用户文件的完整路径保存在密钥文件中。显然,更新后的完整路径不能保证是相同的(我确信这在某处有文档记录,但我没有遇到它)

因此,用户文件已传输到更新的新文档目录,但我在旧的绝对路径中查找它们,即不在我的沙箱中

修复方法是在应用程序的didFinishLaunching中加入一个循环,以拉出文件路径中有问题的文件(我一直在本地查找该文件,但它仍在工作),并将其拆分为文件名。每当执行文件操作时,必须以编程方式查找和添加文档路径


值得一提的是,商店里没有办法恢复到以前的二进制文件,这对我来说是件好事,因为重新安装原始版本不会解决用户的问题,但我相信它已经解决了,至少在最初是这样。我真希望有一种方法可以禁止更新,但仍然允许新的购买(因为问题不影响新的购买)。不过,这种情况可能还不够普遍,不足以证明这一点。

只是想为互联网上的路人提供更多的信息。是的,OP在最后回答了他自己的问题。永远不要在文档目录中存储文件的绝对URL,这样做可能会导致数据丢失。这是因为当您更新应用程序时,通过在.plist文件中更改其版本#,iOS会使用不同的十六进制名称为该应用程序创建一个新目录。现在,您的绝对URL引用的位置不正确,无法返回正确的文件

您可以在自己的计算机上看到这一点,甚至在您通过导航到部署到设备之前

~/Library/Application Support/iPhone Simulator/*ios\u version*/Applications/

在那里,您将看到名称如下的文件夹:

6AA4B05C-8A38-4469-B7BE-5EA7E9712510 CB43C5F3-D720-49C3-87D4-EBE93FFD428B

在这些文件夹中,将是iOS应用程序的标准文件系统布局。i、 e

文件 图书馆 tmp YourApp.app

通过引用整个URL,您将看到如下内容:

~/Library/Application Support/iPhone Simulator/*ios_version*/Applications/6AA4B05C-8A38-4469-B7BE-5EA7E9712510/Documents/MyVeryImportantUserData.txt

但是,当您更新应用程序时,应用程序将尝试的新URL将为:

~/Library/Application Support/iPhone Simulator/*ios_version*/Applications/CB43C5F3-D720-49C3-87D4-EBE93FFD428B/Documents/myveryiimportantuserdata.txt

它是空的

相反,您应该始终进行动态引用,仅在获得documents目录filepath前缀后保存filepath

/**
 Returns the path to the application's Documents directory.
 */
- (NSString *)applicationDocumentsDirectory {
    return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}

对于原始海报,您可以通过发布一个新的更新来保存用户丢失的数据,在该更新中,您修改了代码以获取绝对url并修剪字符串的文档部分的所有内容。然后,您可以在文件路径前面加上正确的文档目录url,应用程序就会找到数据。

问题海报和第一个答案都有助于澄清到底发生了什么

因此,根据他们的观察,我开始意识到,在通向Documents文件夹的路径中,有(看起来是)文件夹的重命名。这使我找到了一个解决方案,在该解决方案中,我只保存文件名,并创建一个实用程序类,用于获取已保存文件名的当前完整路径字符串,该字符串在应用程序更新后现在存储在当前文档文件夹中:

#import "StringUtils.h"

@implementation StringUtils

+ (NSString *)getFullDocumentUrl:(NSString *)fileName
{
    return [NSString stringWithFormat:@"%@/%@",[self applicationDocumentsDirectory],fileName];
}

+ (NSString *)applicationDocumentsDirectory
{
    return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}

@end

我遇到了同样的问题。下面是一些修复文件名的示例代码,通过迭代文档目录中的文件,并在保留文件名的同时替换掉文件路径信息。在执行最后一行更改文件名之前,我建议使用
    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];
    }
NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
// you have photoURl 

func getURLtoUpload(photoUrl:URL) {
    let urlStr = photoUrl.lastPathComponent

    let fileURL = self.getDocumentsDirectory().appendingPathComponent("Temp").appendingPathComponent("\(urlStr)")
    // your url to upload here 
    let url = URL(string:fileURL)
}


func getDocumentsDirectory() -> URL {

    let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    let documentsDirectory = paths[0]
    return documentsDirectory
}