3

I want to use the following method to save NSDictionary

+ (void)writeDicToFile:(NSDictionary *)dic fileName:(NSString *)fileName
{
NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:fileName];
[dic writeToFile:filePath atomically:YES];
}

But for some dictionary it works and for some complex dictionary it doesn't work.

help me!

bohan
  • 1,659
  • 3
  • 17
  • 29
  • 1
    the objects in dictionary have to conform to [ protocol](https://developer.apple.com/library/mac/documentation/cocoa/reference/foundation/Protocols/NSCoding_Protocol/Reference/Reference.html) so they can be (de)serialized – Rok Jarc Dec 23 '13 at 11:33
  • Thank you! I know where the error is now. – bohan Dec 23 '13 at 11:36
  • And I look for ways how to implement that. – bohan Dec 23 '13 at 11:37
  • No problem. What you have to do is implement `encodeWithCoder:` and `initWithCoder:` methods - and tell the compiler that object conforms to this procol by adding `` to the class definition – Rok Jarc Dec 23 '13 at 11:37

2 Answers2

2

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 [].

Rok Jarc
  • 18,765
  • 9
  • 69
  • 124
  • it still doesn't work. I have implement encodeWithCoder: and initWithCoder: methods. help! – bohan Dec 24 '13 at 03:00
  • NSData *data = [NSKeyedArchiver archivedDataWithRootObject:jsonObject]; [data writeToFile:path atomically:YES]; – bohan Dec 24 '13 at 04:54
  • Can you post a bit more on how you generate this jsonObject? With json parsers there is a "problem" that you usually don't know in advance if the result will be dicitonary or an array. And please post your implementation of the two methods. – Rok Jarc Dec 24 '13 at 08:34
  • 1
    thank you for you editing, it's done now. At first I still try to use the `NSDictionary writeToFile:filePath atomically:` method. Thanks a lot @rokjarc – bohan Dec 24 '13 at 12:21
0

The documentation says that :

- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)flag

This method recursively validates that all the contained objects are property list objects (instances of NSData, NSDate, NSNumber, NSString, NSArray, or NSDictionary) before writing out the file, and returns NO if all the objects are not property list objects, since the resultant file would not be a valid property list.

What objects are you puttin in your dictionnary ?
Put property list objects in your dictionary, then there are no reason that it does not work.

you should also see the return value for the method. ( YES or NO).

samir
  • 4,501
  • 6
  • 49
  • 76