首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在NSDocumentDirectory或NSCachesDirectory中保存

在NSDocumentDirectory或NSCachesDirectory中保存
EN

Stack Overflow用户
提问于 2012-10-18 09:03:56
回答 3查看 3.8K关注 0票数 3

已经尝试将我的NSMutableArray对象存储到NSUserDefaults,但是没有任何结果。我的NSMutableArray就在这里包含了这个日志:

代码语言:javascript
复制
`ALAsset - Type:Photo, URLs:assets-library://asset/asset.JPG?id=92A7A24F-D54B-496E-B250-542BBE37BE8C&ext=JPG`

我知道这是一个ALAsset object,在AGImagePickerController中它被比较为NSDictionary,所以我需要做的是保存NSDictionary或数组,然后将它保存到存储ALAsset object的位置,然后将其保存在NSDocuNSCaches中作为一个文件,然后再检索它(这是我的想法)。

但问题是,尽管我尝试了这段代码,但不起作用,而且没有在NSDocuNSCache目录中显示任何内容。

第一次尝试 (info包含ALAsset object):

代码语言:javascript
复制
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
NSString *filePath = [basePath stringByAppendingPathComponent:@"filename.plist"];
NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfURL:filePath];
NSString *error;
NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:plistDict  format:NSPropertyListXMLFormat_v1_0 errorDescription:&error];
if(plistData) {
 [info writeToFile:filePath atomically:YES];
} else {
   NSLog(error);

}

第二次尝试

代码语言:javascript
复制
- (NSString *)createEditableCopyOfFileIfNeeded:(NSString *)_filename {
    // First, test for existence.
    BOOL success;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error;

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *writableFilePath = [documentsDirectory stringByAppendingPathComponent: _filename ];

    success = [fileManager fileExistsAtPath:writableFilePath];
    if (success) return writableFilePath;

    // The writable file does not exist, so copy the default to the appropriate location.
    NSString *defaultFilePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent: _filename ];
    success = [fileManager copyItemAtPath:defaultFilePath toPath:writableFilePath error:&error];
    if (!success) {
        NSLog([error localizedDescription]);
        NSAssert1(0, @"Failed to create writable file with message '%@'.", [error localizedDescription]);
    }
    return writableFilePath;
}

以这样的方式保存:

代码语言:javascript
复制
    NSString *writableFilePath = [self createEditableCopyOfFileIfNeeded:[NSString stringWithString:@"hiscores"]];   
    if (![info writeToFile:writableFilePath atomically:YES]){
        NSLog(@"WRITE ERROR");
    } 

第三次尝试

代码语言:javascript
复制
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:??????];

[info writeToFile:filePath atomically:YES];

第四次尝试(由于其在appbundle中的修改而不确定):https://stackoverflow.com/a/6311129/1302274

还有别的路吗?希望有人能指引我。

EN

回答 3

Stack Overflow用户

发布于 2012-10-18 10:02:07

您可以将NSMutableArray存储到NSUserDefault,方法是将它存档到NSData,而不是通过将其解压缩回NSMutableArray来检索它。

代码语言:javascript
复制
-(NSData*) getArchievedDataFromArray:(NSMutableArray*)arr
{
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:arr];
    return data;
}

-(NSMutableArray*) getArrayFromArchievedData:(NSData*)data
{
    NSMutableArray *arr = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    return arr;
}

用于将数组保存到NSUserDefault:

代码语言:javascript
复制
  [[NSUserDefaults standardUserDefaults] setObject:[self getArchievedDataFromArray: yourArray] forKey:@"YourKey"];
[[NSUserDefaults standardUserDefaults] synchronize];

用于从NSUserDefault检索数组:

代码语言:javascript
复制
NSMutableArray *yourArray = [self getArrayFromArchievedData:[[NSUserDefaults standardUserDefaults]objectForKey:@"YourKey"]];  

此外,还可以将数组以NSData的形式保存到NSDocumentDirectory或NSCachesDirectory中的文件中。希望这有帮助..。

编辑:a UIImage+NSCoding分类

.h文件

代码语言:javascript
复制
#import <UIKit/UIKit.h>

@interface UIImage (NSCoding)
- (id) initWithCoderForArchiver:(NSCoder *)decoder;
- (void) encodeWithCoderForArchiver:(NSCoder *)encoder ;
@end

.m文件

代码语言:javascript
复制
#import "UIImage+NSCoding.h"
#import <objc/runtime.h>
#define kEncodingKey        @"UIImage"

@implementation UIImage (NSCoding)

+ (void) load
{

    @autoreleasepool {
        if (![UIImage conformsToProtocol:@protocol(NSCoding)]) {
            Class class = [UIImage class];
            if (!class_addMethod(
                                 class,
                                 @selector(initWithCoder:), 
                                 class_getMethodImplementation(class, @selector(initWithCoderForArchiver:)),
                                 protocol_getMethodDescription(@protocol(NSCoding), @selector(initWithCoder:), YES, YES).types
                                 )) {
                NSLog(@"Critical Error - [UIImage initWithCoder:] not defined.");
            }

            if (!class_addMethod(
                                 class,
                                 @selector(encodeWithCoder:),
                                 class_getMethodImplementation(class, @selector(encodeWithCoderForArchiver:)),
                                 protocol_getMethodDescription(@protocol(NSCoding), @selector(encodeWithCoder:), YES, YES).types
                                 )) {
                NSLog(@"Critical Error - [UIImage encodeWithCoder:] not defined.");
            }

        } 
    }
}

- (id) initWithCoderForArchiver:(NSCoder *)decoder {
    if (self = [super init]) {
        NSData *data = [decoder decodeObjectForKey:kEncodingKey];
        self = [self initWithData:data];
    }

    return self;

}

- (void) encodeWithCoderForArchiver:(NSCoder *)encoder {

    NSData *data = UIImagePNGRepresentation(self);
    [encoder encodeObject:data forKey:kEncodingKey];

}

@end
票数 2
EN

Stack Overflow用户

发布于 2012-11-06 20:53:17

“writeToFile:原子:”方法的NSArray文档显示,所有成员都必须是属性list对象。ALAsset不是属性列表对象,因此将其写入文件是行不通的。

我知道它是一个ALAsset对象,在AGImagePickerController中它被比较为NSDictionary

如果仔细查看,就会发现它并不比较ALAsset的属性,而是它们的‘ALAssetPropertyURL’属性。该属性的值为NSDictionary。

由于ALAsset没有公共构造函数,所以您无法在读取文件或NSUserDefaults后重新构造它,即使您能够编写它。

因此,您能做的最好的事情就是从最初获得的源中重新获取ALAssets。我想那是ALAssetsGroup?与其保存文件并再次检索,不如在ALAssetsGroup上使用最初用于生成它们的相同查询重新生成它们?

编辑

所以你说你从一个AGImagePickerController得到了原始的资产。为了存储它们,您可以在注释中接受Matej的建议,并存储标识它们的URL。

但是请记住,AGImagePickerController是用户选择多张照片的一种方式,然后会对它们做一些。也就是说,ALAssets只是指向照片的原始位置的中间结果。如果您存储URL并稍后检索它们,则根本无法保证原件仍然在那里。

因此,问问自己:你希望用户对照片做什么,并存储该操作的结果,而不是资产本身。例如,您可以做的一个合理操作是创建一个新的ALAssetGroup (使用ALAssetsLibrary上的addAssetsGroupAlbumWithName:方法),并将资产存储在其中。ALAssetGroups是自动保存的,因此您不需要自己做任何事情。

编辑2 -从OP获得更多信息

Matej在注释中所暗示的是,通过从资产中检索urls,将您拥有的ALAssets数组转换为一个字典数组。正如您可以在ALAsset类文档中阅读一样,您可以这样做:

代码语言:javascript
复制
NSArray *assetArray = // your array of ALAssets
NSMutableArray *urls = [NSMutableArray arrayWithCapacity:assetArray.count];
for( ALAsset *asset in assetArray ) {    
    NSDictionary *urlDictionary = [asset valueForProperty:@"ALAssetPropertyURLs"];
    [urls addObject:urlDictionary];
}

生成的字典数组,可以以任何方式保存。

重新启动应用程序后,您将从存储它的位置读取字典数组。然后,Matej建议使用ALAssetsLibrary的assetForURL:resultBlock:failureBlock:重新创建ALAssets。但是,正如我们现在所知道的,您希望再次对原始资产设置一个复选标记,最好是获取原始的ALAssets数组,并检查它们是否存在于恢复的urls中。为此,应采取以下措施:

代码语言:javascript
复制
NSArray *assetArray = // the full array of ALAssets from AGImagePickerController
NSArray *urls = // the recovered array of NSDictionaries
for( ALAsset *asset in assetArray ) {
    NSDictionary *urlDictionary = [asset valueForProperty:@"ALAssetPropertyURLs"];
    if( [urls containsObject:urlDictionary] ) {
        ... // set checkmark on asset
    }
}

这假设原始资产没有更改,这不在您的控制范围内(例如,用户已经删除/添加了照片)。

票数 1
EN

Stack Overflow用户

发布于 2012-11-01 10:47:19

这是我用来存储数组或字典对象的方法。

代码语言:javascript
复制
- (NSArray*)readPlist
{
    NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); 
    NSString *plistPath = [[documentPaths lastObject] stringByAppendingPathComponent:@"filename.plist"]; 
    NSFileManager *fMgr = [NSFileManager defaultManager];

    if (![fMgr fileExistsAtPath:plistPath]) {
        [self writePlist:[NSArray array]];
    }
    return [NSArray arrayWithContentsOfFile:plistPath];
}

- (void)writePlist:(NSArray*)arr 
{ 
    NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); 
    NSString *plistPath = [[documentPaths lastObject] stringByAppendingPathComponent:@"filename.plist"]; 
    NSFileManager *fMgr = [NSFileManager defaultManager]; 
    if ([fMgr fileExistsAtPath:plistPath]) 
        [fMgr removeItemAtPath:plistPath error:nil]; 

    [arr writeToFile:plistPath atomically:YES]; 
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12950916

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档