1

I have been trying to implement the answers given at is it possible to save NSMutableArray or NSDictionary data as file in iOS? and they have not been working for me. Will someone please inform me of what I am doing wrong? My NSArray is of a custom object, say Cat. Cat itself is constituted of strings and numbers. Here is my code

-(void)saveArrayToFile:(NSArray *)response;
{
//    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
//    NSString *documentsDirectory = [paths objectAtIndex:0];
//    NSString *filePath = [documentsDirectory stringByAppendingPathComponent:PERSISTENT_FILENAME];
//    
//    [response writeToFile:filePath atomically:YES];
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
    if ([paths count] > 0)
    {
        // Path to save array data
        NSString  *arrayPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"array.out"];
        // Write array
        [response writeToFile:arrayPath atomically:YES];


    }else NSLog(@"NO paths");
}

-(NSArray *)getArrayFromFile
{
//    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
//    NSString *documentsDirectory = [paths objectAtIndex:0];
//    NSString *filePath = [documentsDirectory stringByAppendingPathComponent:PERSISTENT_FILENAME];
//    return [NSArray arrayWithContentsOfFile:filePath];
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
    if ([paths count] > 0)
    {
        // Path to save array data
        NSString  *arrayPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"array.out"];
        NSArray *arrayFromFile = [NSArray arrayWithContentsOfFile:arrayPath];
        return arrayFromFile;
    }else NSLog(@"No file to retrieve");
    return nil;
}

First I tried the commented code. Then I tried the other. The problem so far is that the file is not being saved.

Community
  • 1
  • 1
Katedral Pillon
  • 14,534
  • 25
  • 99
  • 199
  • What does an ` NSArray must be a valid property lists` mean? My array is a collection of custom objects. The object itself has strings and numbers. – Katedral Pillon Sep 11 '14 at 01:47
  • Why do you think the provided code does not work? What happened when you ran it? – Jonah Sep 11 '14 at 01:54
  • Property list objects are described in https://developer.apple.com/library/mac/documentation/general/conceptual/devpedia-cocoacore/PropertyList.html – Jonah Sep 11 '14 at 01:56
  • Nothing happens. Absolutely nothing, when I try to save. Rather: after saving when I try to read, the result is always nil. So after further research, I am guessing the problem is that my NSArray's content is not a so called "property list" – Katedral Pillon Sep 11 '14 at 02:13

2 Answers2

4

When you save it [response writeToFile:arrayPath atomically:YES] return false. So it is not saved successfully. Try use

Bool result = [NSKeyedArchiver archiveRootObject:response toFile:arrayPath];
NSArray *arrayFromFile = [NSKeyedUnarchiver unarchiveObjectWithFile:arrayPath];

In your cat file:

@property(nonatomic, strong)NSString* score;
@property(nonatomic, assign)BOOL bGenuine;
@property(nonatomic, assign)NSInteger errorCode;

@synthesize score,bGenuine,errorCode;

- (void)encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:score forKey:@"score"];
    [encoder encodeObject:[NSNumber numberWithBool:bGenuine] forKey:@"bGenuine"];
    [encoder encodeObject:[NSNumber numberWithInt:errorCode] forKey:@"errorCode"];
}

- (id)initWithCoder:(NSCoder *)decoder {
    score = [decoder decodeObjectForKey:@"score"];
    bGenuine = [[decoder decodeObjectForKey:@"bGenuine"] boolValue];
    errorCode = [[decoder decodeObjectForKey:@"errorCode"] integerValue];
    return self;
}
gabbler
  • 13,626
  • 4
  • 32
  • 44
  • The first snippet is to replace your [response writeToFile:arrayPath atomically:YES] and NSArray *arrayFromFile = [NSArray arrayWithContentsOfFile:arrayPath] respectively. The second snippet is to add a new NSObject subclass called Cat. Then you can set your response array to be response = [NSArray arrayWithObjects:cat1, cat2,nil] – gabbler Sep 11 '14 at 04:37
  • I see. I cannot edit the Cat object; it is from server (Google Cloud Endpoint). It seems that the only way is to get the encoder and decoder into the class but besides creating and using a subclass of Cat is there any other way? – Katedral Pillon Sep 11 '14 at 04:44
  • I don't know the structure of your Cat object,is it in JSON format? I think the object mapping is necessary if you want to get the information from your array. – gabbler Sep 11 '14 at 04:53
  • No. It is generated by Google's proprietary engine. But at least with your help, I seem to reach the root cause of my problem. I will keep looking to see how to deal with Google endpoints in this regard. thanks. – Katedral Pillon Sep 11 '14 at 04:56
1

If the array’s contents are all property list objects (NSString, NSData, NSArray, or NSDictionary objects), the file written by this method can be used to initialize a new array with the class method arrayWithContentsOfFile: or the instance method initWithContentsOfFile:.

This might be the reason why you can't read the file if your array contains custom objects

Alternatively try to use NSKeyedArchiver

dopcn
  • 4,218
  • 3
  • 23
  • 32