在NSUserDefaults中保存图像?

Flo*_*rik 78 iphone objective-c ipad ios swift

是否可以将图像保存NSUserDefaults为对象,然后检索以供进一步使用?

Bon*_*nny 137

要在NSUserDefaults中保存图像:

[[NSUserDefaults standardUserDefaults] setObject:UIImagePNGRepresentation(image) forKey:key];
Run Code Online (Sandbox Code Playgroud)

要从NSUserDefaults检索图像:

NSData* imageData = [[NSUserDefaults standardUserDefaults] objectForKey:key];
UIImage* image = [UIImage imageWithData:imageData];
Run Code Online (Sandbox Code Playgroud)

  • 技术上正确,积极不推荐.NSUserDefaults输出到plist,这显然不是原始图像数据的位置. (16认同)
  • @annjawn只需将其写入文件系统,并将URL存储在NSUserDefaults中 (2认同)

Nik*_*ook 83

注意!如果您在iOS8/XCODE6下工作,请查看我的更新

对于那些仍在寻找答案的人来说,这是在NSUserDefaults中保存图像的"可取"方式的代码.您不应该将图像数据直接保存到NSUserDefaults中!

写数据:

// Get image data. Here you can use UIImagePNGRepresentation if you need transparency
NSData *imageData = UIImageJPEGRepresentation(image, 1);

// Get image path in user's folder and store file with name image_CurrentTimestamp.jpg (see documentsPathForFileName below)
NSString *imagePath = [self documentsPathForFileName:[NSString stringWithFormat:@"image_%f.jpg", [NSDate timeIntervalSinceReferenceDate]]];

// Write image data to user's folder
[imageData writeToFile:imagePath atomically:YES];

// Store path in NSUserDefaults
[[NSUserDefaults standardUserDefaults] setObject:imagePath forKey:kPLDefaultsAvatarUrl];

// Sync user defaults
[[NSUserDefaults standardUserDefaults] synchronize];
Run Code Online (Sandbox Code Playgroud)

读取数据:

NSString *imagePath = [[NSUserDefaults standardUserDefaults] objectForKey:kPLDefaultsAvatarUrl];
if (imagePath) {
    self.avatarImageView.image = [UIImage imageWithData:[NSData dataWithContentsOfFile:imagePath]];
}
Run Code Online (Sandbox Code Playgroud)

documentsPathForFileName:

- (NSString *)documentsPathForFileName:(NSString *)name {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsPath = [paths objectAtIndex:0];

    return [documentsPath stringByAppendingPathComponent:name];
}
Run Code Online (Sandbox Code Playgroud)

对于iOS8/XCODE6 如下面的评论中提到的tmr和DevC,xcode6/ios8存在问题.xcode5和xcode 6安装过程之间的区别在于xcode6 在xcode中每次运行后都会更改应用程序UUID(请参阅路径中的高亮部分:/ var/mobile/Containers/Data/Application/B0D49CF5-8FBE-4F14-87AE-FA8C16A678B1/Documents/image.jpg的).

所以有2个解决方法:

  1. 跳过这个问题,因为一旦安装在真实设备上的应用程序,它永远不会改变UUID(事实上它确实如此,但它是新的应用程序)
  2. 保存所需文件夹的相对路径(在我们的示例中为应用程序的根目录)

这是一个快速版本的代码作为奖金(第二种方法):

写数据:

let imageData = UIImageJPEGRepresentation(image, 1)
let relativePath = "image_\(NSDate.timeIntervalSinceReferenceDate()).jpg"
let path = self.documentsPathForFileName(relativePath)
imageData.writeToFile(path, atomically: true)
NSUserDefaults.standardUserDefaults().setObject(relativePath, forKey: "path")
NSUserDefaults.standardUserDefaults().synchronize()
Run Code Online (Sandbox Code Playgroud)

读取数据:

let possibleOldImagePath = NSUserDefaults.standardUserDefaults().objectForKey("path") as String?
if let oldImagePath = possibleOldImagePath {
    let oldFullPath = self.documentsPathForFileName(oldImagePath)
    let oldImageData = NSData(contentsOfFile: oldFullPath)
    // here is your saved image:
    let oldImage = UIImage(data: oldImageData)
}
Run Code Online (Sandbox Code Playgroud)

documentsPathForFileName:

func documentsPathForFileName(name: String) -> String {
    let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true);
    let path = paths[0] as String;
    let fullPath = path.stringByAppendingPathComponent(name)

    return fullPath
}
Run Code Online (Sandbox Code Playgroud)

  • 代码第一次对我不起作用,无法从磁盘检索图像.应用程序运行之间文档文件夹的路径不同.可能是绝对路径与相对路径的问题?代码写入一个*imagePath,但在下一次运行应用程序时,需要一个不同的*imagePath来获取文件.简单的解决方案是只在nsuserdefaults中保存文件名,并在下一个应用程序运行时,重新获取文档文件夹路径,附加文件名,其余代码工作得很好!(谢谢Nikita Took) (2认同)

Fer*_*tes 28

虽然可以保存UIImageNSUserDefaults,但通常不建议这样做,因为它不是保存图像的最有效方法; 更有效的方法是将图像保存在应用程序中Documents Directory.

出于这个问题的目的,我已经附上了你的问题的答案,以及更有效的保存方法UIImage.


NSUserDefaults(不推荐)

保存到NSUserDefaults

此方法允许您将任何内容保存UIImageNSUserDefaults.

-(void)saveImageToUserDefaults:(UIImage *)image ofType:(NSString *)extension forKey:(NSString *)key {
    NSData * data;

    if ([[extension lowercaseString] isEqualToString:@"png"]) {
        data = UIImagePNGRepresentation(image);
    } else if ([[extension lowercaseString] isEqualToString:@"jpg"]) {
        data = UIImageJPEGRepresentation(image, 1.0);
    }

    NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults];
    [userDefaults setObject:data forKey:key];
    [userDefaults synchronize];
}
Run Code Online (Sandbox Code Playgroud)

这就是你怎么称呼它:

[self saveImageToUserDefaults:image ofType:@"jpg" forKey:@"myImage"];
[[NSUserDefaults standardUserDefaults] synchronize];
Run Code Online (Sandbox Code Playgroud)

从NSUserDefaults加载

此方法允许您加载任何UIImage来自NSUserDefaults.

-(UIImage *)loadImageFromUserDefaultsForKey:(NSString *)key {
    NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults];
    return [UIImage imageWithData:[userDefaults objectForKey:key]];
}
Run Code Online (Sandbox Code Playgroud)

这就是你怎么称呼它:

UIImage * image = [self loadImageFromUserDefaultsForKey:@"myImage"];
Run Code Online (Sandbox Code Playgroud)

更好的选择

保存到文档目录

此方法允许您将任何内容保存UIImageDocuments Directory应用程序中.

-(void)saveImage:(UIImage *)image withFileName:(NSString *)imageName ofType:(NSString *)extension inDirectory:(NSString *)directoryPath {
    if ([[extension lowercaseString] isEqualToString:@"png"]) {
        [UIImagePNGRepresentation(image) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"png"]] options:NSAtomicWrite error:nil];
    } else if ([[extension lowercaseString] isEqualToString:@"jpg"] || [[extension lowercaseString] isEqualToString:@"jpeg"]) {
        [UIImageJPEGRepresentation(image, 1.0) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"jpg"]] options:NSAtomicWrite error:nil];
    } else {
        NSLog(@"Image Save Failed\nExtension: (%@) is not recognized, use (PNG/JPG)", extension);
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是你怎么称呼它:

NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
[self saveImage:image withFileName:@"Ball" ofType:@"jpg" inDirectory:documentsDirectory];
Run Code Online (Sandbox Code Playgroud)

从文档目录加载

此方法允许您UIImage从应用程序加载任何Documents Directory.

-(UIImage *)loadImageWithFileName:(NSString *)fileName ofType:(NSString *)extension inDirectory:(NSString *)directoryPath {
    UIImage * result = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/%@.%@", directoryPath, fileName, [extension lowercaseString]]];

    return result;
}
Run Code Online (Sandbox Code Playgroud)

这就是你怎么称呼它:

NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
UIImage * image = [self loadImageWithFileName:@"Ball" ofType:@"jpg" inDirectory:documentsDirectory];
Run Code Online (Sandbox Code Playgroud)

另一种选择

将UIImage保存到照片库

此方法允许您将任何内容保存UIImage到设备Photo Library,并按如下方式调用:

UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
Run Code Online (Sandbox Code Playgroud)

将多个UIImages保存到照片库

此方法允许您将多个保存UIImages到设备Photo Library.

-(void)saveImagesToPhotoAlbums:(NSArray *)images {
    for (int x = 0; x < [images count]; x++) {
        UIImage * image = [images objectAtIndex:x];

        if (image != nil) UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是你怎么称呼它:

[self saveImagesToPhotoAlbums:images];
Run Code Online (Sandbox Code Playgroud)

images你在哪里NSArray组成UIImages.


Bil*_*şek 10

对于Swift 4

我几乎尝试了这个问题中的所有内容,但没有人为我工作.我找到了解决方案.首先,我为UserDefaults创建了一个扩展,如下所示,然后只调用get和set方法.

extension UserDefaults {
    func imageForKey(key: String) -> UIImage? {
        var image: UIImage?
        if let imageData = data(forKey: key) {
            image = NSKeyedUnarchiver.unarchiveObject(with: imageData) as? UIImage
        }
        return image
    }
    func setImage(image: UIImage?, forKey key: String) {
        var imageData: NSData?
        if let image = image {
            imageData = NSKeyedArchiver.archivedData(withRootObject: image) as NSData?
        }
        set(imageData, forKey: key)
    } 
}
Run Code Online (Sandbox Code Playgroud)

在settingsVC中将图像设置为背景我使用下面的代码.

let croppedImage = cropImage(selectedImage, toRect: rect, viewWidth: self.view.bounds.size.width, viewHeight: self.view.bounds.size.width)

imageDefaults.setImage(image: croppedImage, forKey: "imageDefaults")
Run Code Online (Sandbox Code Playgroud)

在mainVC中:

let bgImage = imageDefaults.imageForKey(key: "imageDefaults")!
Run Code Online (Sandbox Code Playgroud)


ali*_*tur 8

对于swift 2.2

储藏:

NSUserDefaults.standardUserDefaults().setObject(UIImagePNGRepresentation(chosenImage), forKey: kKeyImage)
Run Code Online (Sandbox Code Playgroud)

要检索:

if let imageData = NSUserDefaults.standardUserDefaults().objectForKey(kKeyImage),
            let image = UIImage(data: imageData as! NSData){
            // use your image here...
}
Run Code Online (Sandbox Code Playgroud)


War*_*ton 5

是的,技术上可行,如

[[NSUserDefaults standardUserDefaults] setObject:UIImagePNGRepresentation(image) forKey:@"foo"];

但不可取,因为plists不适合大量二进制数据,尤其是User Prefs.最好将图像保存到用户docs文件夹,并将对该对象的引用存储为URL或路径.


Mc.*_*ver 5

对于Swift 3JPG格式

注册默认图像:

UserDefaults.standard.register(defaults: ["key":UIImageJPEGRepresentation(image, 100)!])
Run Code Online (Sandbox Code Playgroud)

保存图片 :

UserDefaults.standard.set(UIImageJPEGRepresentation(image, 100), forKey: "key")
Run Code Online (Sandbox Code Playgroud)

加载图像:

let imageData = UserDefaults.standard.value(forKey: "key") as! Data
let imageFromData = UIImage(data: imageData)!
Run Code Online (Sandbox Code Playgroud)