在NSDocumentDirectory中保存好吗?

时间:2012-07-24 14:04:40

标签: iphone ios xcode

我的应用正在使用NSDocumentDirectory将图像保存在其中,我只想询问它是否是保存图像的安全方式(最多100个)。我已经阅读了几个主题&有关它的答案的问题,虽然我不知道应该遵循哪些。有人说它可以保存在那里。有人说我不应该使用NSDocumentDirectory进行保存,因为它会由iCloud进行备份。那么我在哪里可以保存它,当用户退出应用程序然后再次运行应用程序,然后图像应该仍在那里?我对tmp目录或cache目录不太了解。但如果它是我应该使用的2中的任何一个,我如何在我的代码中使用它们:

                NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory,    NSUserDomainMask ,YES );
                NSString *documentsDir = [paths objectAtIndex:0];
                NSString *savedImagePath = [documentsDir stringByAppendingPathComponent:[NSString stringWithFormat:@"Images%d.png", i]];
                ALAssetRepresentation *rep = [[info objectAtIndex: i] defaultRepresentation];
                UIImage *image = [UIImage imageWithCGImage:[rep fullResolutionImage]];
                //----resize the images
                image = [self imageByScalingAndCroppingForSize:image toSize:CGSizeMake(256,256*image.size.height/image.size.width)];

                NSData *imageData = UIImagePNGRepresentation(image);
                [imageData writeToFile:savedImagePath atomically:YES];

非常感谢您的帮助。

4 个答案:

答案 0 :(得分:19)

iOS会定期清除tmpcache目录。如果图像是一般用途,请使用相机胶卷,因为其他两个答案建议。但是,如果这些图像仅用于您的应用程序范围,您仍然可以安全地将它们存储在Documents目录中,您只需在保存后包含“从iCloud备份中排除”函数调用每个文件,以防止Apple拒绝你的应用程序使用太多的iCloud空间。当然有一个权衡,禁用这意味着如果用户删除应用程序或获取其他设备(等),用户将丢失他们的照片,但这个警告比不在商店中获取应用程序更好。

要禁用文件上的iCloud备份,iOS版本有两种方法> 5.0:

<强> UPDATE!将两种方法合并为自动处理iOS版本的单一功能

#include <sys/xattr.h> // Needed import for setting file attributes

+(BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)fileURL {

    // First ensure the file actually exists
    if (![[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]]) {
        NSLog(@"File %@ doesn't exist!",[fileURL path]);
        return NO;
    }

    // Determine the iOS version to choose correct skipBackup method
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion];

    if ([currSysVer isEqualToString:@"5.0.1"]) {
        const char* filePath = [[fileURL path] fileSystemRepresentation];
        const char* attrName = "com.apple.MobileBackup";
        u_int8_t attrValue = 1;
        int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
        NSLog(@"Excluded '%@' from backup",fileURL);
        return result == 0;
    }
    else if (&NSURLIsExcludedFromBackupKey) {
        NSError *error = nil;
        BOOL result = [fileURL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error];
        if (result == NO) {
            NSLog(@"Error excluding '%@' from backup. Error: %@",fileURL, error);
            return NO;
        }
        else { // Succeeded
            NSLog(@"Excluded '%@' from backup",fileURL);
            return YES;
        }
    } else {
        // iOS version is below 5.0, no need to do anything
        return YES;
    }
}

如果您的应用必须支持5.0,那么不幸的是,您唯一的选择是将这些照片保存在Caches目录中,这意味着它们不会被备份(这不会因此导致App Store拒绝),但每当存储看门狗决定是时候清理Caches文件夹了,你会丢失这些照片。根本不是一个理想的实现,但这就是5.0中的野兽的本质,苹果在备份排除中加入了事后的想法。

编辑:忘记回答'如何保存到tmp / cache目录'部分问题。如果你决定走这条路:

  • 保存到tmp

    NSString *tempDir = NSTemporaryDirectory();
    NSString *savedImagePath = [tempDir stringByAppendingPathComponent:[NSString stringWithFormat:@"Images%d.png", i]];
    

(请注意,这似乎在模拟器中没有任何效果,但它在设备上按预期工作)

  • 保存到Cache

    NSString *cacheDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES)lastObject];
    NSString *savedImagePath = [cacheDir stringByAppendingPathComponent:[NSString stringWithFormat:@"Images%d.png", i]];
    

答案 1 :(得分:2)

如果您希望用户能够使用其他应用中的图像或与照片一起查看,请使用Mike D建议的相册。如果文件是您在本地生成的文件,仅用于您的应用程序,那么您应该使用文档目录。您可以使用info.plist选项“应用程序支持iTunes文件共享”将文档目录公开给iTunes,这将允许用户通过iTunes添加或删除文件,但文件不会公开给其他应用程序

答案 2 :(得分:1)

您正在保存缩放图像,因此它们实际上只对您的游戏有用。它们不会很大,也不会占用太多空间。您可以将它们保存在应用程序的Library目录中,并避免整个iCloud的事情,因为它听起来没有任何理由支持它们。此外,如果由于某些其他原因您已启用iTunes共享,则保存库可避免用户删除它们的可能性。

更新代码,用于保存到应用程序库目录

- (void)saveSequences:(NSMutableDictionary*)sequences
{
    NSArray *path = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
    NSString *libDirectory = [path objectAtIndex:0];
    NSString *settingsPath = [libDirectory stringByAppendingPathComponent:@"userSequences.plist"];

    NSLog(@"settingsPath %@", settingsPath);

    [sequences writeToFile:settingsPath atomically:YES];
}

//下面的代码获取“Documents”文件夹中指定目录的路径 - 如果它不存在,则创建它。如果您决定走这条路线,请将其调整为使用库路径。

- (NSString *)getDirectoryBySequenceName:(NSString *)sequenceName 
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString * documentDirectory = [paths objectAtIndex:0];
    NSString * sequenceDirectory = [documentDirectory stringByAppendingPathComponent:sequenceName];

    NSError *error;
    BOOL success = [[NSFileManager defaultManager] createDirectoryAtPath:sequenceDirectory 
                                             withIntermediateDirectories:YES 
                                                              attributes:nil error:&error];   

    if (!success) {
        NSLog(@"Error creating data path: %@", [error localizedDescription]);
    }

    return sequenceDirectory;
}

答案 3 :(得分:0)

根据您应用的目的,您可以将其保存到照片应用中(我认为UIImageWriteToSavedPhotosAlbum(image, self, nil, nil)Apple reference)。保存在此处或文档目录(或任何子文件夹)中,用户可以将这些图像备份到iCloud或iTunes,如果用户选择和/或他们已经设置了iCloud。

由于您声明图像需要在启动之间保持不变,因此当应用程序从内存中删除时,临时或缓存目录会被清空,可能更快(O / S决定)。

More about the iOS file system