简体   繁体   English

FileExistAtPath在模拟器上运行,但在设备上不运行

[英]FileExistAtPath working on Simulator, but not on Device

In my game, I'm saving stats of the player in a plist that I store in the Documents directory. 在我的游戏中,我将玩家的统计信息保存在我存储在Documents目录中的plist中。 I have an empty dictionary of each stats that should be saved named "Default_Stats.plist" so that if it's the first time the app is loaded, it will copy it in the appropriate directory so it could be loaded and overwritten at will. 对于每个应保存的统计信息,我都有一个空字典,名为“ Default_Stats.plist”,以便在首次加载应用程序时将其复制到适当的目录中,以便可以随意加载和覆盖。 The problem is, every time my app is loaded, it doesn't recognize the "Stats.plist" and overwrite it with the Default Stats, resetting every stats the player have made... And weird enough, it was perfectly working on the simulator, but not on the device. 问题是,每次加载我的应用程序时,它都不会识别“ Stats.plist”,并用默认统计信息覆盖它,重置玩家的所有统计信息……而且很奇怪,它在模拟器,但不在设备上。 Here's my code : 这是我的代码:

In this method I read the stats : 在这种方法中,我读取了统计信息:

- (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];
    }
}

Here's my creating method : 这是我的创建方法:

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

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

    [self writeStatsToFile];
}

And my writing method : 而我的写法

- (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!");
}

Please help, I really don't understand what's wrong! 请帮忙,我真的不明白怎么了! I hope I've made myself clear enough! 我希望我已经足够清楚了!

使用文件路径而不是绝对路径。

Maybe duplicates exist in your mac, which makes exists=true on simulator, but not on device. 也许您的Mac中存在重复项,这在模拟器上使exist = true,但在设备上不存在。

The easiest way to check would be to NSLog the paths encountered. 最简单的检查方法是NSLog遇到的路径。 Refer to these tools - they allow console logs to be captured for release builds running on your device. 请参阅这些工具 -它们允许捕获控制台日志以用于在设备上运行的发行版。

Most likely that your documents directory just doesn't exist - on the simulator you share a documents directory with everyone on the Mac; 很可能您的文档目录不存在-在模拟器上,您与Mac上的所有人共享文档目录; on the device everyone has his own directory. 在设备上,每个人都有自己的目录。 Use the file manager method 使用文件管理器方法

createDirectoryAtURL:url withIntermediateDirectories:YES

to make sure that the directory is there before you try writing there. 在尝试写入目录之前,请确保该目录已存在。 (I tend to use the URL methods instead of the file path methods). (我倾向于使用URL方法而不是文件路径方法)。

PS. PS。 I'd recommend having one method that returns the path or url that you want. 我建议使用一种方法来返回所需的路径或URL。 It's a good habit not to duplicate your code again and again. 一个好习惯是不要一次又一次地复制代码。

I would do pretty much that, like everything in one session: 我会做很多事情,就像在一堂课中做的一切一样:

  1. gets the URL for the file in the Document folder; 获取文档文件夹中文件的URL
  2. if the file is not there yet, copies the file from bundle to the Documents folder; 如果文件尚不存在,请将文件从分发包复制到“ 文档”文件夹;

that should be the method for that, I have defined some macros for avoiding mistyping the file's name in the code: 那应该是它的方法,我已经定义了一些宏,以避免在代码中混淆文件名:

- (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;
}

the URL always points inside the Documents folder, so you will have read/write access to the file – or will be nil if some error happens. URL始终指向Documents文件夹内,因此您将对该文件具有读/写访问权限;如果发生某些错误,则为nil

after you have the URL , you can restore back to file without any issue, and at some other point in runtime you can override the file for your convenience anytime. 拥有URL ,您可以毫无问题地还原回文件,并且在运行时中的其他时间点,您可以随时方便地覆盖文件。


NOTE: you may need to extend this code for a more detailed error handling, I put the comment only the places when you need to worry about potential errors. 注意:您可能需要扩展此代码以进行更详细的错误处理,当您需要担心潜在的错误时,我仅在注释处添加注释。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM