Write Dict to a File

Discussion in 'iOS Programming' started by Depress, Jun 22, 2009.

  1. Depress macrumors newbie

    Joined:
    Jun 22, 2009
    #1
    Hi guys,

    I try to write contents of a dictionary to a file. I use the following code. The paths checkout to be valid. But the functions returns a no.
    Could it be that the file Storage.dat not is created yet.. Because i can't access my device filesystem. On the simulator it also doesn't work.

    What am i doing wrong; i have the following code:
    Code:
    - (int) saveData:(NSString*)EntityName :(NSString*)EntityData
    {
    	NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString* documentsDirectory = [paths objectAtIndex:0];
    	NSString* location = [[NSString alloc] initWithString:[documentsDirectory stringByAppendingString:@"/Storage.dat"]];
    	NSMutableDictionary* data = [[NSMutableDictionary alloc] initWithContentsOfFile: location];
    	[data setObject:EntityData forKey: EntityName];
    	if(![data writeToFile: location atomically: YES])
    		return 0;
    	return 1;
    }
    
    Please help:cool:
     
  2. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #2
    I can't see any obvious errors with that. Have you tried changing the parameter atomically: to NO?
     
  3. PhoneyDeveloper macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #3
    There are some restrictions on the kinds of data that can be in a dictionary or array in order for it to be able to be written out to a file. I think the restriction is that it has to implement NSCoding. Does your EntityData implement NSCoding? What happens if you just read in the dictionary from the file and write it out without adding EntityData?
     
  4. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #4
    Both are declared as NSString in the method signature so they should be OK.
     
  5. Luke Redpath macrumors 6502a

    Joined:
    Nov 9, 2007
    Location:
    Colchester, UK
    #5
    As a side note, that code is going to leak:

    Code:
    NSString* location = [[NSString alloc] initWithString:[documentsDirectory stringByAppendingString:@"/Storage.dat"]];
    	NSMutableDictionary* data = [[NSMutableDictionary alloc] initWithContentsOfFile: location];
    
    should be:

    Code:
    NSString *location = [documentsDirectory stringByAppendingString:@"/Storage.dat"];
    NSMutableDictionary *data = [NSMutableDictionary dictionaryWithContentsOfFile:location];
    
    On the other hand, if you don't want to use autoreleased objects, you'll need to explicitly release the objects instead.
     
  6. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #6
    Even if the path is valid, I would use stringsByAppendingPathComponent instead of stringByAppendingString so that you don't have to deal with the forward slash.
     
  7. eddietr macrumors 6502a

    Joined:
    Oct 29, 2006
    Location:
    Virginia
    #7
    So I'm not sure if you got this already, but the reason this doesn't work is because "data" is nil after the call to - [NSDictionary initWithContentsOfFile]. (This is because the file doesn't yet exist.)

    So then the rest of the calls to [data whatever] don't do a thing.

    Hope that helps.
     
  8. Depress thread starter macrumors newbie

    Joined:
    Jun 22, 2009
    #8
    So the file doesn't exists yet, how should i create the file then? With a string object it is also not going to work, since there is still no file.

    How do i create that (empty) file?
     
  9. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #9

    Create an empty NSMutableDictionary on the first run/when the load from file creates a nil reference and use that instead of the load from file:

    Code:
    NSMutableDictionary* data = [[NSMutableDictionary alloc] initWithContentsOfFile: location];
    if (data == nil)
    {
    	data = [NSMutableDictionary dictionary];
    }
    [data setObject:EntityData forKey: EntityName];
    if(![data writeToFile: location atomically: YES])
    	return 0;
    return 1;
    
     
  10. Luke Redpath macrumors 6502a

    Joined:
    Nov 9, 2007
    Location:
    Colchester, UK
    #10
    A minor niggle but its probably not a good idea to conditionally set the data pointer to either an autoreleased or non-autoreleased object; for consistency I'd make the initial dictionary loaded from the file autoreleased (I'm pretty sure there is a convenience class method dictionaryWithContentsOfFile) too.

    Apart from that, that's exactly how you want to do it.
     
  11. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #11
    Sure, I'd agree with that.
     

Share This Page