6

我的应用程序正在使用它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

4 回答 4

19

和目录由 iOStmp定期cache清理。如果图像用于一般用途,请按照其他两个答案的建议使用相机胶卷。但是,如果这些图像仅适用于您的应用程序范围,您仍然可以安全地将它们存储在 Documents 目录中,您只需在保存后对每个文件添加“从 iCloud 备份中排除”功能调用,以防止 Apple拒绝您的应用程序使用过多的 iCloud 空间。当然有一个权衡,禁用这意味着如果用户删除应用程序或获取其他设备(等),无论如何都会丢失他们的照片,但这个警告比根本不让应用程序进入商店更可取。

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

更新!将两种方法合并为一个自动处理 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 拒绝),但只要存储看门狗决定是时候清理缓存文件夹了,你会丢失这些照片。根本不是一个理想的实现,但这就是 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]];
    
于 2012-07-25T01:09:54.900 回答
2

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

于 2012-07-25T00:39:52.797 回答
1

您正在保存缩放的图像,因此它们实际上只对您的游戏有用。它们不会很大,也不会占用太多空间。您可以将它们保存在应用程序的库目录中,并避免整个 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];
}

// 下面的代码获取到“文档”文件夹中命名目录的路径 - 如果它不存在,则创建它。如果您决定走那条路线,请调整它以使用库路径。

- (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;
}
于 2012-07-25T02:48:30.697 回答
0

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

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

有关 iOS 文件系统的更多信息

于 2012-07-24T14:20:34.123 回答