Saving an Mutable array of images and loading them - ios

I have part of my app that will take a photo and the person can elect to save it i then save the image to an array but what ways can I save it to the phone WITHOUT it being put in the photo library. I tried
UIImage *image = imageView1.image;
[array addObject: image];
NSUserDefaults *default = [NSUserDefault standardDefaults];
[defaults setObject:image withKey:#"saved image"]; //not exact code just showing the method
I use to save the array of images
[defaults synchronize];
then i also use UserDefaults to load array but it does not work. I am wondering if there is a different way to save images without saving them to the photo library.

In principle, you could save the images in NSUserDefaults using
[[NSUserDefaults standardUserDefaults] setObject:UIImagePNGRepresentation(image)
forKey:key];
But keep in mind that NSUserDefaults is meant for storage of preferences, not images. You better save the images in the documents folder and store the path in NSUserDefaults (as suggested by Wain).

You cannot save images the way you want. In your case, array contains just pointers to the images, not images itself. So, one way around is, as #Wain suggested, writing image to the disk, and add path of the saved image to the array, and then saving that array to the NSUserDefaults. You can save image to the disk by converting it to the NSData, and writing it in Documents or tmp folders of application sandbox. In order to convert image to the NSData, you could use UIImageJPEGRepresentation(UIImage *image, CGFloat compressionQuality) method, and in order to write data to the disk, use writeToFile:atomically method of NSData.
Good Luck!

You can save them into the Document directory:
NSData *imageData = UIImagePNGRepresentation(imageView1.image);
NSString *imagePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:#"/imageName.png"];
[imageData writeToFile:imagePath atomically:YES];
And save their URLs in NSUserDefaults:
NSUserDefaults *default = [NSUserDefault standardDefaults];
[defaults setObject:imagePath withKey:#"saved image "];
[defaults synchronize];
And simply retrieve image:
UIImage *customImage = [UIImage imageWithContentsOfFile:imagePath];

Related

UIImage memory change while saved in NSMutableArray

I am saving a UIImage to NSMutableArray. After saving, i am talking the object from array and not getting previous memory.
[self.arrselectedPhotos addObject:[UIImage imageWithData:imageData]];
Currently the size is 191565 (192KB). But when i am taking it from array, the size shows 768786 (750KB+).
UIImage *img=[self.arrselectedPhotos lastObject];
NSLog(#"image size: %lu", (unsigned long)[UIImageJPEGRepresentation(img , 1.0) length]);
What is the problem ?
After 3 days of random R&D, i find out the issue of increasing memory size. I was saving the NSData into array after converting it another image. This is the reason. If i save the NSData directly then everything is ok.
This line is wrong:
[self.arrselectedPhotos addObject:[UIImage imageWithData:imageData]];
And the correct line is:
[self.arrselectedPhotos addObject:imageData];
So i can save it furthur easily.
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self.arrselectedPhotos];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:self.course_name];
[[NSUserDefaults standardUserDefaults] synchronize];

Unable to save data in NSUserDefaults with crash with Signal SIGABRT

I am trying to save NSData in NSUserDefaults in a loop, but I'm constantly getting an error.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *index = [NSString stringWithFormat:#"alltweetsoftrend%d", i];
[defaults setObject:tweetData forKey:index];
[defaults synchronize];
Where i is index of the loop, it means key is not null in any case. I have also checked my NSData(tweetData) and this also is not null. I am just getting this error in saving.
There's nothing inherently wrong with your code. There's a slight chance the NSData is too large to store, but I wouldn't really expect a SIGABRT in that case. The most likely issue is that the NSData was created with [NSData dataWithBytesNoCopy:length:] and the buffer that the NSData pointed to was deallocated. There could be other issues that cause the problem as well, such as using a shared NSData global variable between threads, incorrect typecasting from CFDataRefs, etc, etc.
Try writing a different NSData and see if it works. For example:
NSData *tweetData = [NSData dataWithBytes:"Hello" length:6];. I bet that works, so the problem has to do with how your tweetData was created and sent into this code.

Where to store Dictionary data in iOS

I am developing iPhone app,i have one doubt
I have an NSMutableDictionary which contains data in this format
dict at 0th index:
"ProductId":"77386",
"ProductImage":"http://static.abcd.com/images/product/large/design_gallery_slide_green - Copy (2).jpg",
"Productshortname":"Apple iPhone 5c 16GB",
"categorycode":null,
"categoryid":8,
"categoryimage":"",
"categoryshortname":"",
"favorite":"0",
"price":"31500",
"productnameinUrl":"apple-iphone-5c-16gb",
"storecount":"10"
dict at 1st index:
"ProductId":"11386",
"ProductImage":"http://static.abcd.com/images/product/large/design_gallery_slide_green - Copy (2).jpg",
"Productshortname":"Apple iPhone 5s 16GB",
"categorycode":null,
"categoryid":8,
"categoryimage":"",
"categoryshortname":"",
"favorite":"1",
"price":"31500",
"productnameinUrl":"apple-iphone-5s-16gb",
"storecount":"18"
dict at 2nd index:
"ProductId":"31386",
"ProductImage":"http://static.abcd.com/images/product/large/design_gallery_slide_green - Copy (2).jpg",
"Productshortname":"Apple iPhone 4s 16GB",
"categorycode":null,
"categoryid":8,
"categoryimage":"",
"categoryshortname":"",
"favorite":"1",
"price":"31500",
"productnameinUrl":"apple-iphone-4s-16gb",
"storecount":"38"
and so on...
What i want to do is, i want to store this dictionary indexes some where in my directory and i want to fetch it after some time or even after closing and opening the app after few times.
where should i store this kind of data ? is there any storage for strong this kind of data?
Please help and thanks in advance !!
You can store the data in NSUserdefaults and can access any time and anywhere as you want
yourdict;//Your NSDictionary Object That contains the data to store
[[NSUserDefaults standardUserDefaults] setObject:yourdict forKey:#"dict"];
[[NSUserDefaults standardUserDefaults] synchronize];
At the time of retrieval of data,
dict = [[NSUserDefaults standardUserDefaults] objectForKey:#"dict"];
You've already chosen an approved answer but I'll throw my thoughts in anyway.
This information looks like it could get large.
The user defaults isn't designed for large chunks of data. It's really meant for small bits of information, such as boolean preferences etc etc, not to be treated as an easy-to-use database.
Some problems with the user defaults:
The defaults file is read and parsed when you launch your app, regardless of whether you need your information from it at that time or not. This is because other parts of your app also use it for storing their bits of info too.
The entire defaults file needs to be parsed in order for you to retrieve anything, even if you just want a single entry.
You don't choose when the defaults file is parsed. You can't do any smart threading if it becomes huge (say you put 1000 products in there)
I'd recommend either writing the dictionary to it's own plist using NSDictionary's writeToFile: and reading using initWithContentsOfFile: (this still suffers from point #2 above)
OR
Using CoreData/sqlite to write the information to a real database.
NSDictionary methods: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/Reference/Reference.html#//apple_ref/occ/instm/NSDictionary/writeToFile:atomically:
An other option (And better in my experience) is to use - NSCoder, this option is great as you can use an Object with normal properties to access your data, which make your code more readable.
You can read about it here - NSCoding / NSKeyed​Archiver by NSHipster
An here is the reference - NSCoder docs
NSDictionary has a writeToFile: method which will do it for you.
NSDicationary writeToFile:Atomically:
use NSUserDefault and save your data like this in array
Here you can use this in anyway in your application for store value of NSUserDefaults.
// --- Saving
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// saving an NSString
[prefs setObject:#"TextToSave" forKey:#"keyToLookupString"];
// saving an NSInteger
[prefs setInteger:42 forKey:#"integerKey"];
// saving a Double
[prefs setDouble:3.1415 forKey:#"doubleKey"];
// saving a Float
[prefs setFloat:1.2345678 forKey:#"floatKey"];
// This is suggested to synch prefs, but is not needed (I didn't put it in my tut)
[prefs synchronize];
Here you can use this in anyway in your application for get value of NSUserDefaults.
// --- Retrieving
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// getting an NSString
NSString *myString = [prefs stringForKey:#"keyToLookupString"];
// getting an NSInteger
NSInteger myInt = [prefs integerForKey:#"integerKey"];
// getting an Float
float myFloat = [prefs floatForKey:#"floatKey"];
Thanks & Cheers ..
Looks like there can be more amount of data, so the best approach is to use core data to handle this scenario.
You can check few tutorials on how to use core data - Link1 , Link2
There are advantage of using core data over NSUserDefault and file system, as those load all the data at once and you might face some issue in performance.
You can also check following links which will illustrate you performance of different mechanism used to store data - PerformanceLinks1 PerformanceLinks2
try this
NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:
#"audio.caf",#"pictureAudioKey",
#"audio.m4a",#"englishAudioKey",
#"audio2.m4a",#"spanishAudioKey",
#"audio3.m4a",#"frenchAudioKey",
#"audio4.m4a",#"germanAudioKey",
#"audio5.m4a",#"italianAudioKey",
#"audio6.m4a",#"chineseAudioKey",
#"image.jpg",#"photoimagekey",
#"name.txt", #"identity",
#"imagename.txt",#"numberkey",nil];
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [documentPaths objectAtIndex:0];
NSString *dictionaryPath = [documentsDirectory stringByAppendingPathComponent:[[self imageNameTextField]text]];
dictionaryPath =[dictionaryPath stringByAppendingFormat:#"dicitonary" ] ;
NSDictionary *savedDictionary = dictionary;
NSLog(#"The Save file is:%#", savedDictionary);
[savedDictionary writeToFile:dictionaryPath atomically:YES];

Save image in NSUserDefaults [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I need to store and retrieve images in my app, I first thought of doing it like so:
[[NSUserDefaults standardUserDefaults] setObject:UIImagePNGRepresentation(image) forKey:key];
NSData* imageData = [[NSUserDefaults standardUserDefaults] objectForKey:key];
UIImage* image = [UIImage imageWithData:imageData];
But I read this isn't the recommended way. What is the best approach for this?
(I know there are duplicates of this question, but I haven't understood how to do it yet)
The best way to store images depends on what your app does.
If you have 100k+ images you probably want to save it manually to the iphone's hard disk over coredata since it will load images faster this way.
However, if you have less than that, then storing images as binary data in core data is what I would recommend.
The benefits of using coredata vs the file system:
Better iCloud Sync Support
No need to manage images on the hard disk as well as what ever you use as a 'persistence store' (coredata/nsuserdefaults/custom)
You can tie images to other data such as name, created date, ect.
Some interesting performance info with filesystem vs coredata: http://biasedbit.com/filesystem-vs-coredata-image-cache/
You'd have to take the data from UIImageJPEGRepresentation() and store it in an NSData object or some such in order for it to be "plist-serializable" to store in NSUserDefaults, but as others have said, you're much better off storing the image as an image file on the file system somewhere and storing the file path or file URL in NSUserDefaults.
Save the image in the Documents directory, then save the file name in a database (Core Data perhaps), another file format or NSUserDefaults.
NSUserDefaults is not really a great way to store app data.
From a UIImage instance get the data with
UIImagePNGRepresentation() or UIImageJPEGRepresentation(). Then save the data to a file. Use imageWithContentsOfFile: to recover the UIImage.
To obtain the path to the documents directory:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths firstObject];
The easiest way for you is to directly save the content to your iOS Device and store the path in the NSUserDefaults.
First convert the image to a file and save it to the phone.
UIImage *image = // your image
NSData *pngImageData = UIImagePNGRepresentation(image);
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths firstObject];
NSString *fileName = [NSString stringWithFormat:#"%#/imageName.png",
documentsDirectory];
[pngImageData writeToFile:fileName atomically:YES];
Some are against storing filePaths in NSUserDefaults because, you're not suppose to store anything in NSUserDefaults that is super dynamic, you're suppose to store things like session keys, or token values, user names even, things that don't change often or are very strict.
The suggestion is, if you absolutely refuse CoreData, to make a property list and store the string name there.
To store your imagePath in a plist you would do the following:
NSString *textPath = [[NSBundle mainBundle] pathForResource:#"propertyListName" ofType:#"plist"];
NSDictionary *thisDict = [NSDictionary dictionaryWithContentsOfFile:textPath];
NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithDictionary:thisDict];
mutableDictionary[#"key"] = fileName;
[mutableDictionary writeToFile:resultsPath atomically:YES];
To retrieve your image from a plist you would do the following
NSString *textPath = [[NSBundle mainBundle] pathForResource:#"propertyListName" ofType:#"plist"];
NSDictionary *thisDict = [NSDictionary dictionaryWithContentsOfFile:textPath];
NSString *imagePath = thisDict[#"key"];
NSData *imageData = [NSData dataWithContentsOfFile:filePath];
UIImage *myImage = [UIImage imageWithData:imageData];
Do not use this NSUserDefaults option for it is wrong, but if you wanted to, this is how you would do it.
[[NSUserDefaults standardUserDefaults] setObject:fileName forKey:#"key"];
[[NSUserDefaults standardUserDefaults] synchronize];
now it's saved easily for you to retrieve. When you want to retrieve the image.
NSString *filePath = [[NSUserDefaults standardUserDefaults] objectForKey:#"key"];
NSData *imageData = [NSData dataWithContentsOfFile:filePath];
UIImage *myImage = [UIImage imageWithData:imageData];
then use myImage as the image. Remember the key must be the same when setting and retrieving.
The best way to store images depends on what your app does.
If you have 100k+ images you probably want to save it manually to the iphone's hard disk over coredata since it will load images faster this way.
However, if you have less than that, then storing images as binary data in core data is what I would recommend.
The benefits of using coredata vs the file system:
Better iCloud Sync Support
No need to manage images on the hard disk as well as what ever you use as a 'persistence store' (coredata/nsuserdefaults/custom)
You can tie images to other data such as name, created date, ect.
Some interesting performance info with filesystem vs coredata: http://biasedbit.com/filesystem-vs-coredata-image-cache/

What else do I need to save a variable into disc?

I'me trying to save a variable into hard drive to load it on my app startup. I do the following:
paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentsDirectory = [paths objectAtIndex:0];
votesFile = [documentsDirectory stringByAppendingPathComponent:#"votes.dat"];
Yet, this is creating no file, at least that I can see. When I try to do this:
[votes writeToFile:votesFile atomically:YES]; //votes!=nil
and then
votes = [[NSMutableDictionary alloc] initWithContentsOfFile: votesFile];
it does nothing for me, votes == nil
What am I missing here?
If you are using a NSDictionary with NSStrings as keys, and NSNumbers as values, those classes are compatible with Archiving and Unarchiving pattern, so you can use NSUserDefaults to store your data, and load it the next time you run the application.
To save your data:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:yourVotesDictionary forKey:aKey];
[defaults synchronize]; //This is very important when you finish saving all your data.
To load your data:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableDictionary *votes = [defaults objectForKey:yourNSString];
As you can see, NSUserDefaults is a dictionary, and it behaves like that.
Hope it helps,
have a good day.
There can be various errors using writeToFile:atomically: which is why it returns a BOOL. You should have something like:
if(![votes writeToFile:votesFile atomically:YES]) {
NSLog(#"An error occurred");
}
If you are getting an error there you have an issue with your NSDictionary.

Resources