FileExistAtPath在Simulator上工作,但在Device上没有

时间:2013-01-07 16:06:22

标签: ios objective-c cocoa-touch plist nsfilemanager

在我的游戏中,我将玩家的统计数据保存在我存储在Documents目录中的plist中。我有一个空的字典,应该保存每个属性名为" Default_Stats.plist"因此,如果它是第一次加载应用程序,它会将其复制到相应的目录中,以便可以随意加载和覆盖它。问题是,每次我的应用程序加载时,它都不会识别" Stats.plist"并使用默认统计信息覆盖它,重置播放器制作的每个统计数据......奇怪的是,它完全适用于模拟器,但不在设备上。这是我的代码:

在这种方法中,我阅读统计数据:

- (void) readStatsFromFile{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *statsPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Stats.plist"];

    //Check if the file has already been created
    if (![[NSFileManager defaultManager] fileExistsAtPath:statsPath]){
        [self createStatsList];
    }else{
        stats = [[NSMutableDictionary dictionaryWithContentsOfFile:statsPath]retain];
    }
}

这是创建方法:

- (void) createStatsList{
    NSString *statsPath = [[NSBundle mainBundle] bundlePath];
    statsPath = [statsPath stringByAppendingPathComponent:@"Default_Stats.plist"];

    stats = [[NSMutableDictionary dictionaryWithContentsOfFile:statsPath] retain];

    [self writeStatsToFile];
}

我的写作方法:

- (void) writeStatsToFile{
    BOOL ok;
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *statsPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Stats.plist"];
    ok = [stats writeToFile:statsPath atomically:YES];

    if (!ok) {
        NSLog(@"Couldn't write to file");
    }else
        NSLog(@"Stats written succesfully!");
}

请帮助,我真的不明白什么是错的!我希望我已经足够清楚了!

4 个答案:

答案 0 :(得分:0)

使用filepath而不是绝对路径。

答案 1 :(得分:0)

你的mac中可能存在重复项,这会使模拟器上的exists = true,但不会出现在设备上。

最简单的检查方法是NSLog遇到的路径。请参阅these tools - 它们允许为您设备上运行的发布版本捕获控制台日志。

答案 2 :(得分:0)

您的文档目录很可能不存在 - 在模拟器上,您与Mac上的所有人共享文档目录;在设备上每个人都有自己的目录。使用文件管理器方法

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"></script>
<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>prop demo</title>
  <style>
    p {
      margin: 20px 0 0;
    }
    b {
      color: blue;
    }
  </style>

</head>

<body>

  <input id="check1" type="checkbox" checked="checked">
  <label for="check1">Check me</label>
  <p></p>

  <script>
    $("input").change(function() {
      var $input = $(this);
      $("p").html(
        ".attr( \"checked\" ): <b>" + $input.attr("checked") + "</b><br>" +
        ".prop( \"checked\" ): <b>" + $input.prop("checked") + "</b><br>" +
        ".is( \":checked\" ): <b>" + $input.is(":checked")) + "</b>";
    }).change();
  </script>

</body>

</html>

在尝试编写目录之前确保目录存在。 (我倾向于使用URL方法而不是文件路径方法)。

PS。我建议使用一个方法返回您想要的路径或网址。不要一次又一次地复制代码是一个好习惯。

答案 3 :(得分:0)

我会做的很多,就像一次会议中的所有事情一样:

  1. 获取 Document 文件夹中文件的URL;
  2. 如果文件尚未存在,请将文件从复制到 Documents 文件夹;
  3. 应该是方法,我已经定义了一些宏来避免在代码中输入错误的文件名:

    - (NSURL *)statsFileURL {
    #define NSStringFromFileNameWithExtension(filename, extension) [(filename) stringByAppendingPathExtension:(extension)]
    #define kExtension @"plist"
    #define kDefaultStatsFileName @"Default_Stats"
    #define kCustomStatsFileName @"Stats"
    
        NSURL *_returnURL = nil;
    
        NSFileManager *_fileManager = [NSFileManager defaultManager];
        NSURL *_documentDirectory = [[_fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
        NSURL *_myFileURLInDocumentFolder = [_documentDirectory URLByAppendingPathComponent:NSStringFromFileNameWithExtension(kDefaultStatsFileName, kExtension)];
        if ([_fileManager fileExistsAtPath:[_myFileURLInDocumentFolder path]]) {
            _returnURL = _myFileURLInDocumentFolder;
        } else {
            NSURL *_myFileURLInBundle = [[NSBundle mainBundle] URLForResource:kDefaultStatsFileName withExtension:kExtension];
            if ([_fileManager fileExistsAtPath:[_myFileURLInBundle path]]) {
                NSError *_error = nil;
                if ([_fileManager copyItemAtURL:_myFileURLInBundle toURL:_myFileURLInDocumentFolder error:&_error]) {
                    if (_error == nil) {
                        _returnURL = _myFileURLInDocumentFolder;
                    } else {
                        // some error during copying
                    }
                } else {
                    // some error during copying
                }
            } else {
                // the file does not esixts at all, not even in the bundle
            }
        }
    
        return _returnURL;
    }
    

    URL始终指向 Documents 文件夹,因此您将拥有该文件的读/写权限 - 如果发生某些错误,则会nil

    拥有URL之后,您可以毫无问题地还原回文件,并且在运行时的其他时间点,您可以随时覆盖文件以方便使用。

    注意:您可能需要扩展此代码以进行更详细的错误处理,我只在需要担心潜在错误时将注释放在位置。