How can I store NSMutableArray of custom objects?
I have this code for loading and saving files:
- (NSMutableArray *)loadDataFromFile:(NSString *)fileName {
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [paths objectAtIndex:0];
NSString *path = [docDir stringByAppendingPathComponent:fileName];
NSFileManager *fileMgr = [NSFileManager defaultManager];
if (![fileMgr fileExistsAtPath:path]) {
NSArray *fileArray = [fileName componentsSeparatedByString:#"."];
NSString *name = [fileArray objectAtIndex:0];
NSString *ext = [fileArray objectAtIndex:1];
NSString *bundle = [[NSBundle mainBundle] pathForResource:name ofType:ext];
[fileMgr copyItemAtPath:bundle toPath:path error:&error];
}
NSMutableArray *data = [[NSMutableArray alloc] initWithContentsOfFile:path];
return data;
}
- (void)saveData:(NSMutableArray *)arrayData toFile:(NSString *)filename forKey:(NSString *)key {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [paths objectAtIndex:0];
NSString *path = [docDir stringByAppendingPathComponent:filename];
[arrayData writeToFile: path atomically:YES];
NSLog(#"%#", arrayData);
}
But when I used data.plist as filename, it didn't work because NSLog(#"%#", arrayData); returns list custom object adresses:
"AreaTableRecord: 0x76a7ef0"
This custom object is inserted to array using this code:
AreaTableRecord *area=[[AreaTableRecord alloc] init];
area.title=title;
area.lastScore=0;
area.vocabulary=[[NSMutableArray alloc] init];
[self.areas addObject:area];
How could I store NSMutableArray self.areas that contains custom objects AreaTableRecord?
and
What file format shloud I use to store this data? (it seems to me that plist is not working in this case)
You are only able to store primitive data types in NSDefaults or a plist. In order to work around this you can either choose to store your information in a database....or encode your objects as byte streams and then save them into a file.
Take a look at this thread. It details how to go about encoding your objects.
Basically you need to add these methods to your custom class:
- (void)encodeWithCoder:(NSCoder *)encoder
{
//Encode properties, other class variables, etc
[encoder encodeObject:self.question forKey:#\"question\"];
[encoder encodeObject:self.categoryName forKey:#\"category\"];
[encoder encodeObject:self.subCategoryName forKey:#\"subcategory\"];
}
- (id)initWithCoder:(NSCoder *)decoder
{
self = [super init];
if( self != nil )
{
//decode properties, other class vars
self.question = [decoder decodeObjectForKey:#\"question\"];
self.categoryName = [decoder decodeObjectForKey:#\"category\"];
self.subCategoryName = [decoder decodeObjectForKey:#\"subcategory\"];
}
return self;
}
And then in order to use them you make calls as such:
For setting:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *myEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:obj];
[defaults setObject:myEncodedObject forKey:#\"myEncodedObjectKey\"];
For retrieving:
NSUserDefaults defaults = [NSUserDefaults standardUserDefaults];
NSData *myEncodedObject = [defaults objectForKey: key];
MyCustomObject* obj = (MyCustomObject*)[NSKeyedUnarchiver unarchiveObjectWithData: myEncodedObject];
Related
I am creating a plist of dictionaries. The plist starts off as empty, and then I do this:
NSMutableArray *favouritesList = [[NSMutableArray alloc] initWithContentsOfFile:path];
[favouritesList addObject:thisPlace]; // where thisPlace is some NSDictionary
[favouritesList writeToFile:path atomically:YES];
When I immediately do:
NSArray *savedFav = [[NSArray alloc] initWithContentsOfFile:path];
NSLog(#"%#", savedFav);
I get an empty array. Why is this? Why isn't it writing properly? I am setting up the plist correctly, I debugged that. But I cannot add a dictionary to it.
The plist is just an empty plist with a root that's an array
EDIT:
Here is how I construct my path:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"favourites.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:path]) {
NSString *sourcePath = [[NSBundle mainBundle] pathForResource:#"favourites" ofType:#"plist"];
[fileManager copyItemAtPath:sourcePath toPath:path error:nil];
}
I do something like below. I add an object using a key. Maybe that's why it's not working.
static NSMutableDictionary *dictionaryStore;
+(void)initialize{
if(dictionaryStore == nil){
dictionaryStore = [[NSMutableDictionary alloc] initWithContentsOfFile:[self getFilePath]];
if(dictionaryStore == nil)
dictionaryStore = [NSMutableDictionary new];
}
}
+(NSString *)getFilePath{
NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *plistPath = [rootPath stringByAppendingPathComponent:#"filename.plist"];
return plistPath;
}
+(NSString *)getValueForKey:(NSString *)key{
[self initialize];
return [dictionaryStore objectForKey:key];
}
+(void)setValue:(NSString *)value forKey:(NSString *)key{
[self initialize];
[dictionaryStore setValue:value forKey:key];
}
+(BOOL)save{
[self initialize];
return [dictionaryStore writeToFile:[self getFilePath] atomically:YES];
}
Edit:
So to save a value, I do:
[WAStore setValue:myValue forKey:myKey];
BOOL isSuccessful = [WAStore save];
WAStore is the class name. myValue can be most data types (NSManagedObjectModels won't work). myKey is any NSString.
i am new to iPhone developer, i am creating ePub reader for reading ePub files.
I have plist in my iphone app and I want to read and write data to my .plist file, in which i am facing problem.
here is my code snippet,
Logic: first i am downloading an ePub file, .ePub file will be downloaded to this path
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
NSLog(#"basePath=%#",basePath);
output :-
=/Users/krunal/Library/Application Support/iPhone Simulator/5.1/Applications/6B7FCD58-EDF9-44F4-8B33-5F3542536F92/Documents
now, i want to write name of Downloaded .ePubfile into file into my .plist
code:
NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithContentsOfFile: basePath];
[data setObject:[NSNumber numberWithInt:value] forKey:#"value"];
[data writeToFile: plistPath atomically:YES];
[data release];
i tried this, but i am unable to write in my .plist file.
Any Help Will be Appriciated.
Thanks In Advance !!
Did you mean:
NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithContentsOfFile: plistPath];
?
untested code follows:
Step 1: Copy the file to it's folder.
NSError *error1;
BOOL resourcesAlreadyInDocumentsDirectory;
BOOL copied1;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath1 = [documentsDirectory stringByAppendingString:#"/epub.plist"];
resourcesAlreadyInDocumentsDirectory = [fileManager fileExistsAtPath:filePath1];
if(resourcesAlreadyInDocumentsDirectory == YES) {
} else {
NSString *path1 = [[[NSBundle mainBundle] resourcePath] stringByAppendingFormat:#"/epub.plist"];
copied1 = [fileManager copyItemAtPath:path1 toPath:filePath1 error:&error1];
if (!copied1) {
NSAssert1(0, #"Failed to copy epub.plist. Error %#", [error1 localizedDescription]);
}
}
Step 2:Open it
NSMutableDictionary* dict = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath1];
Step 3:Write data to it
[dict setObject:[NSNumber numberWithInt:value] forKey:#"value"];
[dict writeToFile:path atomically:YES];
NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithContentsOfFile: basePath];
data is nil here, you should init it with:
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
Edited my answer to be more clear:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
if ( basePath == nil ) {
return
}
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
[data setObject:[NSNumber numberWithInt:value] forKey:#"value"];
NSString *plistPath = [NSString stringWithFormat:#"%#/name.plist", basePath];
[data writeToFile: plistPath atomically:YES];
[data release];
It is easer for you to use NSUserDefault, you data will be saved to a plist file as following code:
- (void)setOverviewGroupInstrument:(BOOL)isGroupded {
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:[Your array] forKey:[Your Key]];
[prefs synchronize];
}
Then you can read by:
- (NSMutableArray*)getOverviewInstrumentList {
return [prefs objectForKey:[Your Key]];
}
I am new in iphone, i want to save NSMutableArray data into plist file my Code is:
NSArray *array = [[NSArray alloc] initWithArray:self.artistDetailsArray];
[self.artistDetailsArray writeToFile:self.path atomically:YES];
but it shows 0 element in my plist path. please any help me.
Thanks in advance:
following is my code to store the data into plist and NSUserDefault.
none of them is working for NSMutableArray/NSArray but working for NSString. IS there any max size limit to store in plist or UserDefault??
NSMutableArray contains only text/ set of NSDictionary.
please suggest me.
- (void)initialiseDataFromLocalStorage
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
self.path = [documentsDirectory stringByAppendingPathComponent:#"saveLogin.plist"];
if ([fileManager fileExistsAtPath:self.path] == NO) {
NSString *pathToDefaultPlist = [[NSBundle mainBundle] pathForResource:#"saveLogin" ofType:#"plist"];
if ([fileManager copyItemAtPath:pathToDefaultPlist toPath:self.path error:&error] == NO) {
NSAssert1(0,#"Failed with error '%#'.", [error localizedDescription]);
}
}
// To get stored value from .plist
NSDictionary *dict = [[NSDictionary alloc]initWithContentsOfFile:self.path];
self.ResumedataDictionary = [[NSMutableDictionary alloc]initWithDictionary:dict];
[dict release];
self.artistDetailsArray = [[NSMutableArray alloc] initWithArray:[self.ResumedataDictionary objectForKey:#"artistDetailsDict"]];
// To get stored value from NSUserDefault
NSUserDefaults *fetchData = [NSUserDefaults standardUserDefaults];
self.artistDetailsArray = [fetchData objectForKey:#"artistDetailsDict"];
}
-(void)saveDataToLocalStorage
{
// To store value into .plist
NSArray *array = [[NSArray alloc] initWithArray:self.artistDetailsArray];
[ResumedataDictionary setObject:array forKey:#"artistDetailsDict"];
[ResumedataDictionary writeToFile:self.path atomically:YES];
// To store value into NSUserDefault
NSUserDefaults *fetchData = [NSUserDefaults standardUserDefaults];
[fetchData setObject:self.artistDetailsArray forKey:#"artistDetailsDict"];
}
NSMutableArray *array=[[NSMutableArray alloc] init];
[array addObject:#"test"];
[array writeToFile:#"/Users/parag/test.plist" atomically:YES];
[array release];
or
NSMutableArray *array=[[NSMutableArray alloc] init];
[array addObject:#"test121"];
id plist = [NSPropertyListSerialization dataFromPropertyList:(id)array format:NSPropertyListXMLFormat_v1_0 errorDescription:#error];
[plist writeToFile:#"/Users/parag/test.plist" atomically:YES];
Take a look at Creating Property Lists Programmatically
look at this code which creates path to plist in documents directory:
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //1
NSString *documentsDirectory = [paths objectAtIndex:0]; //2
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"data.plist"]; //3
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path]) //4
{
NSString *bundle = [[NSBundle mainBundle] pathForResource:#”data” ofType:#”plist”]; //5
[fileManager copyItemAtPath:bundle toPath: path error:&error]; //6
}
1) Create a list of paths.
2) Get a path to your documents directory from the list.
3) Create a full file path.
4) Check if file exists.
5) Get a path to your plist created before in bundle directory (by Xcode).
6) Copy this plist to your documents directory.
next read data:
NSMutableDictionary *savedStock = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
//load from savedStock example int value
int value;
value = [[savedStock objectForKey:#"value"] intValue];
[savedStock release];
write data:
NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
//here add elements to data file and write data to file
int value = 5;
[data setObject:[NSNumber numberWithInt:value] forKey:#”value”];
[data writeToFile: path atomically:YES];
[data release]
You can use property lists (NSPropertyListSerialization or writeToFile: way).
But be sure your array contains valid property list objects only (NSString, NSNumber, NSData, NSArray, or NSDictionary objects) and NSDictionary has only NSString keys. Custom (complex) objects have to be represented as dictionaries.
Or you should use approach with archives http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Archiving/Archiving.html through NSCoding protocol.
Nice guide is here http://cocoadevcentral.com/articles/000084.php
NSData *serializedData;
NSString *error;
serializedData = [NSPropertyListSerialization dataFromPropertyList:YourArray(You can use dictionaries.strings..and others too)
format:NSPropertyListXMLFormat_v1_0 errorDescription:&error];
if (serializedData) {
// Serialization was successful, write the data to the file system // Get an array of paths.
NSArray *documentDirectoryPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [NSString stringWithFormat:#”%#/serialized.xml”,
[documentDirectoryPath objectAtIndex:0]];
[serializedData writeToFile:docDir atomically:YES];
}
else {
// An error has occurred, log it
NSLog(#”Error: %#”,error); }
}
I have the following block of code:
NSMutableArray* mergedSymbolsArray = [NSMutableArray array];
for (NSDictionary* aSymbol in localSet) {
NSLog(#"Symbol:%#",[aSymbol valueForKey:#"symbol"]);
[mergedSymbolsArray addObject:aSymbol];
}
[Utils writeObjectToPList:mergedSymbolsArray];
tickers = [Utils getDataFromPList];
Here is my code to read/write to a plist:
+ (void)writeObjectToPList:(id)myData {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"mobile-watchlist.plist"];
[myData writeToFile:path atomically:YES];
}
+(NSMutableArray*)getDataFromPList
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"mobile-watchlist.plist"];
NSMutableArray* myArray = [[NSMutableArray alloc] initWithContentsOfFile:path];
NSLog(#"READING -- PList Data Count: %d", [myArray count]);
return [[NSMutableArray alloc] initWithContentsOfFile:path];
}
For some reason mergedSymbolsArray will not write to a plist. I am not sure why?
I am able to write the following into a plist:
[tickers addObject:[NSDictionary dictionaryWithObjectsAndKeys:#"GOOG", #"symbol", #"2044", #"id", nil]];
[tickers addObject:[NSDictionary dictionaryWithObjectsAndKeys:#"AAPL", #"symbol", #"686", #"id", nil]];
[tickers addObject:[NSDictionary dictionaryWithObjectsAndKeys:#"YHOO", #"symbol", #"4177", #"id", nil]];
[Utils writeObjectToPList:tickers];
Why doesn't the first block of code write to a plist?
ADDITIONAL NOTES:
Here is an example of a dictionary the mergedSymbolsArray contains:
{
"charts_count" = 2;
"created_at" = "2010-04-12T16:37:32Z";
exchange = NASDAQ;
"followers_count" = 259;
id = 8404;
industry = "<null>";
"messages_count" = 1436;
ric = "GRPN.O";
sector = "<null>";
symbol = GRPN;
title = Groupon;
"updated_at" = "2011-09-05T04:17:56Z";
}
I am guessing the writeToFile:atomically method is failing because cannot be written?
Make sure all the objects you keep in the array are the property list objects (NSString, NSData, NSArray, or NSDictionary).
It fails because dta contains sector = "<null>" whose value is interpreted as NSNull and cannot be written to a plist.
I convert NSArray or NSDictionary to NSData before serializing. Following is a category on nsarray for serializing and deserializing. This comfortableby handles some data being nsnull
-(BOOL)writeToPlistFile:(NSString*)filename{
NSData * data = [NSKeyedArchiver archivedDataWithRootObject:self];
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentsDirectory = [paths objectAtIndex:0];
NSString * path = [documentsDirectory stringByAppendingPathComponent:filename];
BOOL didWriteSuccessfull = [data writeToFile:path atomically:YES];
return didWriteSuccessfull;
}
+(NSArray*)readFromPlistFile:(NSString*)filename{
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentsDirectory = [paths objectAtIndex:0];
NSString * path = [documentsDirectory stringByAppendingPathComponent:filename];
NSData * data = [NSData dataWithContentsOfFile:path];
return [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
Check the return value of [myData writeToFile:path atomically:YES]; please. If it's NO, some errors have occurred while writing.Try to alloc-init the NSMutableArray instead of creating an autoreleased one.
Try adding a forward slash to your file name Ie:
NSString *path = [documentsDirectory stringByAppendingString:#"/mobile-watchlist.plist"];
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to write data in plist?
hi i am now in iphone programming. i want ti add data and save it in plist ....-
i am using following code...
(void)viewDidLoad {
[super viewDidLoad];
NSLog(#"i amin did load");
temp =[self readPlist:data];
NSLog(#"dict data is %#",temp);
[self writeToPlist];
temp =[self readPlist:data];
NSLog(#"dict data is %#",temp);
}
//
// NSError *error;
// NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //1
// NSString *documentsDirectory = [paths objectAtIndex:0]; //2
// NSString *path = [documentsDirectory stringByAppendingPathComponent:#"data.plist"]; //3
//
// NSFileManager *fileManager = [NSFileManager defaultManager];
//
// if (![fileManager fileExistsAtPath: path]) //4
// {
// NSString *bundle = [[NSBundle mainBundle] pathForResource:#"data" ofType:#"plist"]; //5
//
// [fileManager copyItemAtPath:bundle toPath: path error:&error]; //6
// }
// NSMutableDictionary *savedStock = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
//
// NSLog(#"dictionary value is %#",savedStock);
//
// value = [[savedStock objectForKey:#"india"] intValue];
// NSLog(#"value in plist is %d",value);
// [savedStock release];
- (NSDictionary *)readPlist:(NSString *)fileName
{ NSLog(#"i am in readlist method");
NSLog(#"file paased is %#",fileName);
//NSData *plistData;
// NSString *error;
// NSPropertyListFormat format;
// NSDictionary *plist;
NSString *filePath = [[NSBundle mainBundle] pathForResource:fileName ofType:#"plist"];
NSMutableDictionary *plistDict=[[NSMutableDictionary alloc] initWithContentsOfFile:filePath];
return plistDict;
}
- (void)writeToPlist
{
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"data" ofType:#"plist"];
NSMutableDictionary* plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath];
[plistDict setValue:#"karachi" forKey:#"pakistan"];
[plistDict setObject:#"lahore" forKey:#"amerika"];
[plistDict setObject:#"jabalpur" forKey:#"mp"];
[plistDict writeToFile:filePath atomically: YES];
/* This would change the firmware version in the plist to 1.1.1 by initing the NSDictionary with the plist, then changing the value of the string in the key "ProductVersion" to what you specified */
}
When you call writeToFile:atomically you don't need to give the full path, just the file name. It will automatically put it in the documents directory.
Basically, everywhere where you have written the variable filePath just write #"whatever.plist".