【问题标题】:FileExistAtPath working on Simulator, but not on DeviceFileExistAtPath 在模拟器上工作,但不在设备上
【发布时间】:2012-12-21 09:33:54
【问题描述】:

在我的游戏中,我将玩家的统计数据保存在我存储在 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!");
}

请帮忙,我真的不明白出了什么问题!我希望我已经说得够清楚了!

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

    • 你能说得更具体些吗?
    【解决方案2】:

    您的 mac 中可能存在重复项,这使得在模拟器上存在=true,但在设备上不存在。

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

    【讨论】:

      【解决方案3】:

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

      createDirectoryAtURL:url withIntermediateDirectories:YES
      

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

      PS。我建议使用 one 方法来返回您想要的路径或 url。不要一次又一次地重复你的代码是一个好习惯。

      【讨论】:

        【解决方案4】:

        我几乎会这样做,就像一个会话中的所有内容一样:

        1. 获取Document文件夹中文件的URL
        2. 如果文件还没有,则将文件从 bundle 复制到 Documents 文件夹;

        应该是这样的,我已经定义了一些宏来避免在代码中输入错误的文件名:

        - (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 之后,您可以毫无问题地恢复到文件,并且在运行时的某个其他时间点,您可以随时覆盖该文件以方便您使用。


        注意:您可能需要扩展此代码以进行更详细的错误处理,我只在您需要担心潜在错误的地方添加注释。

        【讨论】:

          猜你喜欢
          • 2012-08-19
          • 2023-03-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多