How to Save Nsmutablearray or Nsdictionary Data as File in iOS

is it possible to save NSMutableArray or NSDictionary data as file in iOS?

To write in file


NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:FILE_NAME];

[myArray writeToFile:filePath atomically:YES];

To read from file


NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:FILE_NAME];

myArray = [NSArray arrayWithContentsOfFile:filePath];

myArray will be nil if file is not present. And NSDictionary has similar methods. Please check the reference for the details of these methods.

Is there any restrictions on save NSDictionary to file

In order for NSDictionary to be successfully saved all the objects it holds have to conform to NSCoding protocol.

In short that means that you have to implement

- (void)encodeWithCoder:(NSCoder *)encoder

and

- (id)initWithCoder:(NSCoder *)decoder

for all your custom classes.

A nice tutorial is here: http://www.raywenderlich.com/1914/nscoding-tutorial-for-ios-how-to-save-your-app-data

EDIT:

Once you have written you NSCoder methods you can save data like this:

NSMutableData *data = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:self];
[archiver finishEncoding];
[data writeToFile:file atomically:YES];

And init the object from file like this:

NSData *data = [[NSData alloc] initWithContentsOfFile:file];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
self = [unarchiver decodeObject];
[unarchiver finishDecoding];

You did mention having problems with json object: the thing about json object is that first you have to check its type: it can be a NSDictionary or a NSArray - depending on the input and format.

Common problem occours when you get an array with only one element - dictionary you are looking for. This happens if your dictionary {...} json representation is embedded within [].

How to store Value of NSDictionary to NSMutableArray in loop?

You need to create a new NSMutableDictionary *dRow on every iteration:

- (NSDictionary *) getPreparedAllRow
{

//NSMutableDictionary *dRow=[[NSMutableDictionary alloc]init];
NSMutableArray *data=[[NSMutableArray alloc]init];

int counter=0;
while(sqlite3_step(statment) == SQLITE_ROW)
{
int Column_Count = sqlite3_column_count(statment);

NSMutableDictionary *dRow=[[NSMutableDictionary alloc]init];

if(Column_Count >= 1)
{

for(int count =0 ; count < Column_Count ; count++)
{
[dRow setObject:[self columnValue:count] forKey:@(sqlite3_column_name(statment, count))];
//dRow [ @(sqlite3_column_name(statment, count))] = [self columnValue:count];
}
}
NSLog(@"%@",dRow);
[data insertObject:dRow atIndex:counter];
counter++;
NSLog(@"%@",data);
}
NSLog(@"%@",data);
return dRow;
}

And I think that you want to return the NSMutableArray*?? maybe you have an error there too...

Save NSMutableArray in iOS

If your array contains non-plist objects, then you cannot use NSUserDefaults without first encoding the array.

The value parameter can be only property list objects: NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. For NSArray and NSDictionary objects, their contents must be property list objects.

You'll want to encode it using NSKeyedArchiver. This will give you an NSData object that you can then store in NSUserDefaults, or write it to file through NSKeyedArchiver itself.

All you have to do is conform to NSCoding in your custom object, and override initWithCoder: to initialise your object when it's loaded and encodeWithCoder: to encode your variables when it gets encoded. For example, your custom object will look something like this:

@interface customArrayObject : NSObject <NSCoding>

@property (nonatomic) NSString* foo;

@property (nonatomic) NSInteger bar;

@end

@implementation customArrayObject

-(instancetype) initWithCoder:(NSCoder *)aDecoder { // decode variables
if (self = [super init]) {
_foo = [aDecoder decodeObjectForKey:@"foo"];
_bar = [aDecoder decodeIntegerForKey:@"bar"];
}
return self;
}

-(void) encodeWithCoder:(NSCoder *)aCoder { // encode variables
[aCoder encodeObject:_foo forKey:@"foo"];
[aCoder encodeInteger:_bar forKey:@"bar"];
}

@end

It's also worth noting that NSUserDefaults is used to store user preferences, and therefore if your array contains data that isn't in any way to do with a user preference, you shouldn't be using NSUserDefaults - you should be writing it to disk yourself.

Writing your array to disk is actually a lot more trivial than it sounds, you can use the archiveRootObject:toFile: method on NSKeyedArchiver. For example, this will write your custom array to the documents directory:

// Gets the documents directory path
NSString* documentsPath = NSSearchPathForDirectoriesInDomains(directory, NSUserDomainMask, YES)[0];

// Archive and save the file to foo.dat in the documents directory. Returns whether the operation was successful.
BOOL success = [NSKeyedArchiver archiveRootObject:customArray toFile:[NSString stringWithFormat:@"%@/%@", documentsPath, @"foo.dat"]]

However, it is also worth noting that this flat (yes/no) as to whether the operation was successful isn't that great when it comes to error handling. If you want to implement custom error handling, then you'll want to first encode the object using NSKeyedArchiver's archivedDataWithRootObject: method, and then NSData's writeToFile:options:error: method.

Saving NSMutableArray to the iPhone Documents Directory

You can not save your array of objects because objects are not NSString, NSData, NSArray, or NSDictionary.You could rather use NSKeyArchiver and NSKeyUnArchiver

For example:
#import "Foundation/Foundation.h"

@interface Dog : NSObject {**NSCoding**}//your class must conform to NSCoding Protocol  
@property (retain) NSString *Name;
@end

The implementation needs some additional code. We need to implement the NSCoding protocol, which means
two additional methods. (initWithCoder: and encodeWithCoder:)
#import "Dog.h"

@implementation Dog 
@synthesize Name;
-(id)initWithCoder:(NSCoder*)decoder{
if ((self = [super init])) {
Name = [decoder decodeObjectForKey:@"Name"];
}
return self;
}

-(void)encodeWithCoder:(NSCoder*)encoder{
[encoder encodeObject:Name forKey:@"Name"];
}

Once we implement the protocol, saving will look like this:

// Save method

// We initialise our object and set the values

Dog *dog1 = [[Dog alloc] init];  
dog1.Name= @"Dog1";
Dog *dog2 = [[Dog alloc] init];
dog2.Name= @"Dog2";
Dog *dog3 = [[Dog alloc] init];
dog3.Name= @"Dog3";
NSMutableArray *arrayDogs = [NSMutableArray array];
[arrayDogs addObject: dog1];
[arrayDogs addObject: dog2];
[arrayDogs addObject: dog3];

//Sorts the array in alphabetical order according to name – compareDogNames: is defined in the Dog class

arrayDogs = (NSMutableArray *)[arrayDogs sortedArrayUsingSelector:@selector(compareDogNames:)];  

// Store the array

[NSKeyedArchiver archiveRootObject:arrayDogs toFile:dogFilePath];  

//load the array*

NSMutableArray* retreivedADogObjs = [NSKeyedUnarchiver unarchiveObjectWithFile:dogFilePath]; 
@end

Hope it will help you

Happy to help.*

Store Empty NSMutableArray in NSDictionary

There's nothing wrong with storing an empty array in a dictionary.
For example:

NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSMutableArray *array = [NSMutableArray array];
dict[@"array"] = array;

Storing a nil pointer that's declared as a pointer to an array would be a problem, however.

How to save NSMutablearray in NSUserDefaults

Note: NSUserDefaults will always return an immutable version of the object you pass in.

To store the information:

// Get the standardUserDefaults object, store your UITableView data array against a key, synchronize the defaults
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:arrayOfImage forKey:@"tableViewDataImage"];
[userDefaults setObject:arrayOfText forKey:@"tableViewDataText"];
[userDefaults synchronize];

To retrieve the information:

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSArray *arrayOfImages = [userDefaults objectForKey:@"tableViewDataImage"];
NSArray *arrayOfText = [userDefaults objectForKey:@"tableViewDataText"];
// Use 'yourArray' to repopulate your UITableView

On first load, check whether the result that comes back from NSUserDefaults is nil, if it is, you need to create your data, otherwise load the data from NSUserDefaults and your UITableView will maintain state.

Update

In Swift-3, the following approach can be used:

let userDefaults = UserDefaults.standard

userDefaults.set(arrayOfImage, forKey:"tableViewDataImage")
userDefaults.set(arrayOfText, forKey:"tableViewDataText")
userDefaults.synchronize()

var arrayOfImages = userDefaults.object(forKey: "tableViewDataImage")
var arrayOfText = userDefaults.object(forKey: "tableViewDataText")


Related Topics



Leave a reply



Submit