Ist es möglich, Bilder NSUserDefaults
als Objekt zu speichern und zur weiteren Verwendung abzurufen?
Antworten:
BEACHTUNG! WENN SIE UNTER iOS8 / XCODE6 ARBEITEN, SEHEN SIE MEIN UPDATE UNTEN
Für diejenigen, die hier noch nach einer Antwort suchen, gibt es den Code "ratsam", um Bilder in NSUserDefaults zu speichern. Sie sollten Bilddaten NICHT direkt in NSUserDefaults speichern!
Daten schreiben:
// 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];
Daten lesen:
NSString *imagePath = [[NSUserDefaults standardUserDefaults] objectForKey:kPLDefaultsAvatarUrl];
if (imagePath) {
self.avatarImageView.image = [UIImage imageWithData:[NSData dataWithContentsOfFile:imagePath]];
}
documentsPathForFileName:
- (NSString *)documentsPathForFileName:(NSString *)name {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
return [documentsPath stringByAppendingPathComponent:name];
}
Für iOS8 / XCODE6 Wie in den Kommentaren unten erwähnt, gibt es ein Problem mit xcode6 / ios8. Der Unterschied zwischen dem Installationsprozess von xcode5 und xcode 6 besteht darin, dass xcode6 die UUID von Apps nach jeder Ausführung in xcode ändert (siehe hervorgehobenes Teil im Pfad: / var / mobile / Container / Daten / Anwendung / B0D49CF5-8FBE-4F14-87AE-FA8C16A678B1 / Documents / image.jpg).
Es gibt also zwei Problemumgehungen:
Hier ist eine schnelle Version des Codes als Bonus (mit 2. Ansatz):
Daten schreiben:
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()
Daten lesen:
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)
}
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
}
So speichern Sie ein Bild in NSUserDefaults:
[[NSUserDefaults standardUserDefaults] setObject:UIImagePNGRepresentation(image) forKey:key];
So rufen Sie ein Bild von NSUserDefaults ab:
NSData* imageData = [[NSUserDefaults standardUserDefaults] objectForKey:key];
UIImage* image = [UIImage imageWithData:imageData];
Das Speichern von UIImage
to ist zwar möglich NSUserDefaults
, wird jedoch häufig nicht empfohlen, da dies nicht die effizienteste Methode zum Speichern von Bildern ist. Eine effizientere Möglichkeit besteht darin, Ihr Bild in der Anwendung zu speichern Documents Directory
.
Für die Zwecke dieser Frage habe ich die Antwort an Ihre Frage angehängt, zusammen mit der effizienteren Methode zum Speichern von a UIImage
.
Speichern in NSUserDefaults
Diese Methode ermöglicht es Ihnen , alle retten UIImage
zu NSUserDefaults
.
-(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];
}
So nennt man es:
[self saveImageToUserDefaults:image ofType:@"jpg" forKey:@"myImage"];
[[NSUserDefaults standardUserDefaults] synchronize];
Laden aus NSUserDefaults
Mit dieser Methode können Sie beliebige UIImage
von laden NSUserDefaults
.
-(UIImage *)loadImageFromUserDefaultsForKey:(NSString *)key {
NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults];
return [UIImage imageWithData:[userDefaults objectForKey:key]];
}
So nennt man es:
UIImage * image = [self loadImageFromUserDefaultsForKey:@"myImage"];
Speichern im Dokumentenverzeichnis
Mit dieser Methode können Sie alle UIImage
in Documents Directory
der App speichern .
-(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);
}
}
So nennt man es:
NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
[self saveImage:image withFileName:@"Ball" ofType:@"jpg" inDirectory:documentsDirectory];
Laden aus dem Dokumentenverzeichnis
Mit dieser Methode können Sie alle UIImage
aus der Anwendung laden Documents Directory
.
-(UIImage *)loadImageWithFileName:(NSString *)fileName ofType:(NSString *)extension inDirectory:(NSString *)directoryPath {
UIImage * result = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/%@.%@", directoryPath, fileName, [extension lowercaseString]]];
return result;
}
So nennt man es:
NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
UIImage * image = [self loadImageWithFileName:@"Ball" ofType:@"jpg" inDirectory:documentsDirectory];
Speichern von UIImage in der Fotobibliothek
Diese Methode ermöglicht das Speichern UIImage
auf dem Gerät Photo Library
und wird wie folgt aufgerufen:
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
Speichern mehrerer UIImages in der Fotobibliothek
Mit dieser Methode können Sie mehrere UIImages
auf dem Gerät speichern 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);
}
}
So nennt man es:
[self saveImagesToPhotoAlbums:images];
Wo images
ist Ihr NSArray
bestehend aus UIImages
.
inDirectory:(NSString *)directoryPath
- können Sie es einfach so nennen, wie Sie möchten, wie "myAppData"?
Für Swift 4
Ich habe fast alles in dieser Frage versucht, aber niemand ist für mich gearbeitet. und ich fand meine Lösung. Zuerst habe ich eine Erweiterung für UserDefaults wie unten erstellt und dann einfach get and set Methoden aufgerufen.
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)
}
}
Um das Bild als Hintergrund in settingsVC festzulegen, habe ich den folgenden Code verwendet.
let croppedImage = cropImage(selectedImage, toRect: rect, viewWidth: self.view.bounds.size.width, viewHeight: self.view.bounds.size.width)
imageDefaults.setImage(image: croppedImage, forKey: "imageDefaults")
in mainVC:
let bgImage = imageDefaults.imageForKey(key: "imageDefaults")!
Für schnelle 2.2
Lagern:
NSUserDefaults.standardUserDefaults().setObject(UIImagePNGRepresentation(chosenImage), forKey: kKeyImage)
So rufen Sie ab:
if let imageData = NSUserDefaults.standardUserDefaults().objectForKey(kKeyImage),
let image = UIImage(data: imageData as! NSData){
// use your image here...
}
Ja, technisch möglich wie in
[[NSUserDefaults standardUserDefaults] setObject:UIImagePNGRepresentation(image) forKey:@"foo"];
Dies ist jedoch nicht ratsam, da Plists keine geeigneten Orte für große Blobs von Binärdaten sind, insbesondere für Benutzereinstellungen. Es ist besser, das Bild im Ordner "Benutzerdokumente" zu speichern und den Verweis auf dieses Objekt als URL oder Pfad zu speichern.
Für Swift 3 und JPG- Format
Standardbild registrieren:
UserDefaults.standard.register(defaults: ["key":UIImageJPEGRepresentation(image, 100)!])
Bild speichern :
UserDefaults.standard.set(UIImageJPEGRepresentation(image, 100), forKey: "key")
Bild laden :
let imageData = UserDefaults.standard.value(forKey: "key") as! Data
let imageFromData = UIImage(data: imageData)!
Aus der Apple-Dokumentation,
Die NSUserDefaults-Klasse bietet bequeme Methoden für den Zugriff auf gängige Typen wie Floats, Doubles, Integer, Boolesche Werte und URLs. Ein Standardobjekt muss eine Eigenschaftsliste sein, dh eine Instanz von (oder für Sammlungen eine Kombination von Instanzen von): NSData, NSString, NSNumber, NSDate, NSArray oder NSDictionary. Wenn Sie einen anderen Objekttyp speichern möchten, sollten Sie ihn normalerweise archivieren, um eine Instanz von NSData zu erstellen.
Sie können das Bild folgendermaßen speichern: -
[[NSUserDefaults standardUserDefaults] setObject:UIImagePNGRepresentation([UIImage imageNamed:@"yourimage.gif"])forKey:@"key_for_your_image"];
Und lesen Sie so: -
NSData* imageData = [[NSUserDefaults standardUserDefaults]objectForKey:@"key_for_your_image"];
UIImage* image = [UIImage imageWithData:imageData];
Es ist technisch möglich, aber nicht ratsam. Speichern Sie das Image stattdessen auf der Festplatte. NSUserDefaults ist für kleine Einstellungen gedacht, nicht für große Binärdatendateien.
Bild in NSUserDefault speichern:
NSData *imageData;
// create NSData-object from image
imageData = UIImagePNGRepresentation([dic objectForKey:[NSString stringWithFormat:@"%d",i]]);
// save NSData-object to UserDefaults
[[NSUserDefaults standardUserDefaults] setObject:imageData forKey:[NSString stringWithFormat:@"%d",i]];
Bild von NSUserDefault laden:
NSData *imageData;
// Load NSData-object from NSUserDefault
imageData = [[NSUserDefaults standardUserDefaults] valueForKey:[NSString stringWithFormat:@"%d",i]];
// get Image from NSData
[image setObject:[UIImage imageWithData:imageData] forKey:[NSString stringWithFormat:@"%d",i]];
Ja, du kannst verwenden. Da es sich jedoch um die Speicherung von Einstellungen handelt, können Sie Bilder besser im Dokumentordner speichern.
Und Sie können den Pfad NSUserDefaults
bei Bedarf in der haben.
Da diese Frage einen hohen Google-Suchindex hat, finden Sie hier die Antwort von @ NikitaTook in der heutigen Zeit, dh Swift 3 und 4 (mit Ausnahmebehandlung).
Hinweis: Diese Klasse dient ausschließlich zum Lesen und Schreiben von Bildern im JPG-Format in das Dateisystem. Das Userdefaults
Zeug sollte außerhalb davon gehandhabt werden.
writeFile
Nimmt den Dateinamen Ihres JPG-Bildes (mit der Erweiterung .jpg) und das UIImage
selbst auf und gibt true zurück, wenn es speichern kann, oder false, wenn es das Bild nicht schreiben kann. An diesem Punkt können Sie das Bild in Userdefaults
welchem speichern wäre Ihr Backup-Plan oder versuchen Sie es einfach noch einmal. Die readFile
Funktion nimmt den Namen der Bilddatei auf und gibt a zurück UIImage
. Wenn der an diese Funktion übergebene Bildname gefunden wird, gibt sie das Bild zurück. Andernfalls wird nur ein Standard-Platzhalterbild aus dem Asset-Ordner der App zurückgegeben (auf diese Weise können Sie böse Abstürze oder andere vermeiden seltsame Verhaltensweisen).
import Foundation
import UIKit
class ReadWriteFileFS{
func writeFile(_ image: UIImage, _ imgName: String) -> Bool{
let imageData = UIImageJPEGRepresentation(image, 1)
let relativePath = imgName
let path = self.documentsPathForFileName(name: relativePath)
do {
try imageData?.write(to: path, options: .atomic)
} catch {
return false
}
return true
}
func readFile(_ name: String) -> UIImage{
let fullPath = self.documentsPathForFileName(name: name)
var image = UIImage()
if FileManager.default.fileExists(atPath: fullPath.path){
image = UIImage(contentsOfFile: fullPath.path)!
}else{
image = UIImage(named: "user")! //a default place holder image from apps asset folder
}
return image
}
}
extension ReadWriteFileFS{
func documentsPathForFileName(name: String) -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let path = paths[0]
let fullPath = path.appendingPathComponent(name)
return fullPath
}
}
Swift 4.x
Xcode 11.x.
func saveImageInUserDefault(img:UIImage, key:String) {
UserDefaults.standard.set(img.pngData(), forKey: key)
}
func getImageFromUserDefault(key:String) -> UIImage? {
let imageData = UserDefaults.standard.object(forKey: key) as? Data
var image: UIImage? = nil
if let imageData = imageData {
image = UIImage(data: imageData)
}
return image
}