【问题标题】:non-persistence of object written to documentsDirectory - is写入documentsDirectory的对象的非持久性 - 是
【发布时间】:2015-01-23 17:15:56
【问题描述】:

--关于如何使保存到文档目录的对象在驱动器上持久存在并且在iDevice重新启动后可恢复的问题。

这是我的问题。我用 NSCoding 制作了一个数据对象并用数据填充它。每次更新对象中的数据时,我都会将其写入documentsDirectory。我停止应用程序并再次启动应用程序,我的数据对象及其所有数据仍然存在。但是,如果我重新启动 iPhone,我为恢复和读取数据对象而编写的代码将失败。

我最初编写的代码仅使用 NSString 作为文件路径。它在ios7下运行良好,但在ios8下失败。

阅读资料后,我从 Apple 文档中找到了这条线索:

“重要提示:虽然它们在您的应用程序运行时可以安全使用,但文件引用 URL 在您的应用程序启动之间存储和重用是不安全的,因为如果系统重新启动,文件的 ID 可能会更改。如果您想存储在您的应用程序启动之间永久保存文件的位置,请按照使用书签定位文件中的说明创建书签。"

所以我重写了我的 ios7 文件打开和文件关闭方法,因此它们不再使用字符串或 URL,而是从使用 NSUserDefaults 保存的书签中获取它们的字符串和 URL。同样的问题:只要我不关闭手机,一切都会正常工作,但一旦我关闭,一切都会丢失。我无法解决这个问题。

这是我目前的一系列步骤。首先,我使用书签确定(或者如果它已经存在于 NSUsrDefaults 中,我恢复)documentsDirectory 的绝对路径:

 + (NSString*) getGeoModelAbsolutePath
 {
     NSString *path;
     NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
     NSURL *documentsDirectoryBookmarkURL;
     NSData* documentsDirectoryBookmark = [userDefaults objectForKey:@"documentDirectoryBookmark"];
     if(documentsDirectoryBookmark == nil)
     {
         documentsDirectoryBookmarkURL = [self getDocumentsDirectoryURL];
         documentsDirectoryBookmark = [self bookmarkForURL:documentsDirectoryBookmarkURL];
     }
     documentsDirectoryBookmarkURL = [self urlForBookmark:documentsDirectoryBookmark];
     path = documentsDirectoryBookmarkURL.path;
     path = [path stringByAppendingString:@"/Model.mod"];

     return path;
 }

使用从我的 ios7 代码修改的方法(仅使用 getDocumentsDirectory 方法):

 + (NSString *)getDocumentsDirectory
 {
     NSURL *directory = [self getDocumentsDirectoryURL];
     NSString * documentsDirectory = directory.path;
     return documentsDirectory;
 } 

 + (NSURL *)getDocumentsDirectoryURL
 {
      NSURL *directory = [[[NSFileManager defaultManager]
                      URLsForDirectory:NSDocumentDirectory
                      inDomains:NSUserDomainMask]
                     lastObject];
     return directory;
 }

 + (NSData*)bookmarkForURL:(NSURL*)url {
     NSError* theError = nil;
     NSData* bookmark = [url bookmarkDataWithOptions:NSURLBookmarkCreationSuitableForBookmarkFile
                      includingResourceValuesForKeys:nil
                                       relativeToURL:nil
                                               error:&theError];
     if (theError || (bookmark == nil)) {
         // Handle any errors.
         return nil;
     }
     return bookmark;
 }

所以现在我有了一个带有模型文件名的 NSString 路径,我可以使用它来访问 GeoModel

 - (GeoModel*) openGeoModel
 {

     GeoModel *geoModel;
     NSString* documentsDirectoryGeoModel =[FileManager getGeoModelAbsolutePath];



     if([FileManager fileExistsAtAbsolutePath:documentsDirectoryGeoModel])
     {

         NSData* data = [NSData dataWithContentsOfFile: documentsDirectoryGeoModel]; //]documentsDirectoryGeoModel];
         geoModel = [NSKeyedUnarchiver unarchiveObjectWithData: data];
         NSString *unarchivedGeoModelVersion = geoModel.geoModel_VersionID;

         if(![unarchivedGeoModelVersion isEqual: currentGeoModelVersion])
         {
             [FileManager deleteFile:documentsDirectoryGeoModel];
             geoModel = [GeoModel geoModelInit];
             [Utilities setGeoProjectCounter:0];
         }

     }
     else
     {
         geoModel  = [GeoModel geoModelInit];
     }

     [FileManager saveGeoModel];
     return geoModel;

 }

然后我可以将其保存到documentsDirectory,如下所示:

 + (BOOL)saveGeoModel
 {

     NSError *error = nil;
     NSString *path = [self getGeoModelAbsolutePath];
     [NSKeyedArchiver archiveRootObject:appDelegate.currentGeoModel toFile:path];

     NSData* encodedData = [NSKeyedArchiver archivedDataWithRootObject: appDelegate.currentGeoModel];
     BOOL success = [encodedData writeToFile: path options:NSDataWritingAtomic error:&error];

  return success;  
 }

这总是成功的——但只有在我不关闭设备的情况下才会持久!我没有在这方面取得任何进展:任何帮助将不胜感激!

提前致谢

蒂姆·雷德菲尔德

【问题讨论】:

  • 对。我不认为这有资格回答我自己的问题——因为我犯的错误不在这段代码中。 (我没有以正确的顺序保存数据:
  • (续)——我过早地保存了,所以数据对象中没有任何内容:未归档的为 nil。
  • (抱歉——键盘很敏感)。我的观点:上面的代码实际上运行得很好,并且是持久的——只要你以正确的顺序将一个数据对象写入到 documentDirectory 中,这样它就可以在其中包含数据,并且不为零。在上面的示例中,我的本地 geoModel 实例有数据,但因为我过早地保存了它,所以我的应用程序的其余部分看到的是一个不存在的对象。
  • 对于任何寻求类似答案的人来说,还有一点:更短的方法可能是
  • NSData* encodedData = [NSKeyedArchiver archivedDataWithRootObject: geoModell]; NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; [userDefaults setObject:encodedData forKey:@"archivedGeoModel"]; [用户默认同步];

标签: ios8 nscoding


【解决方案1】:

那里。我认为它已经得到了回答——除非其他人对如何改进上述列表有意见,否则他们会按应有的方式工作!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-25
    • 1970-01-01
    • 1970-01-01
    • 2021-04-05
    • 2013-06-04
    • 2010-12-26
    • 2021-11-07
    • 1970-01-01
    相关资源
    最近更新 更多