NSCoding with as NSString inside a object
Asked Answered
A

1

8

My issue is then I retrieve my NSArray of Store objects, all my NSString properties are causing BadAccess errors. The int and double properties work fine!

store.h

@interface Store : NSObject<NSCoding> {
    NSString *Name;
    NSString *Address;
    NSString *Phone;
    double GeoLong;
    double GeoLat;
    int ID;         
}

@property (nonatomic, retain) NSString *Name;
@property (nonatomic, retain) NSString *Address;
@property (nonatomic, retain) NSString *Phone;
@property (nonatomic) double GeoLat;
@property (nonatomic) double GeoLong;
@property (nonatomic) int ID;

@end

store.m

@implementation Store

@synthesize Name;
@synthesize ID;
@synthesize Address;
@synthesize Phone;
@synthesize GeoLat;
@synthesize GeoLong;


/** Implentation of the NSCoding protocol. */

-(void)encodeWithCoder:(NSCoder *)encoder
{
    [encoder encodeInt:ID forKey:@"ID"];
    [encoder encodeDouble:GeoLat forKey:@"GeoLat"];
    [encoder encodeDouble:GeoLong forKey:@"GeoLong"];
    NSLog(@"Name in encode: %@", Name); //WORKS!
    [encoder encodeObject:Name forKey:@"Name"];
    [encoder encodeObject:Phone forKey:@"Phone"];
    [encoder encodeObject:Address forKey:@"Address"];

}

-(id)initWithCoder:(NSCoder *)decoder
{
    // Init first.
    if(self = [self init]){

    ID = [decoder decodeIntForKey:@"ID"];
    GeoLat = [decoder decodeDoubleForKey:@"GeoLat"];
    GeoLong = [decoder decodeDoubleForKey:@"GeoLong"];
    Name = [decoder decodeObjectForKey:@"Name"];
    NSLog(@"Name in decode: %@", Name); //WORKS! logs the name

    Address = [decoder decodeObjectForKey:@"Address"];
    Phone = [decoder decodeObjectForKey:@"Phone"];
    }

    return self;
}

- (void)dealloc
{
    [Name release];
    [ID release];
    [Address release];
    [Phone release];


    [super dealloc];
}
@end

Here is my code for storing and retriving the array.

//streams contains the data i will populate my array with. 
for (ndx = 0; ndx < streams.count; ndx++) {
            NSDictionary *stream = (NSDictionary *)[streams objectAtIndex:ndx];

            Store *item = [[Store alloc] init] ;
            item.Name = [stream valueForKey:@"Name"];
            item.Address = [stream valueForKey:@"Address"];
            item.Phone = [stream valueForKey:@"Phone"];
            item.GeoLat = [[stream valueForKey:@"GeoLat"] doubleValue];
            item.GeoLong = [[stream valueForKey:@"GeoLong"] doubleValue];                
            item.ID = [[stream valueForKey:@"ID"] intValue]; 

            [listToReturn addObject:item];
        }
    }

    //test to check if it works
    for(int i = 0; i < [listToReturn count]; i++){
        Store *item = (Store *)[listToReturn objectAtIndex:i];
        NSLog(@"Name: %@", item.Name); //works
    }

    //save
    [[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:listToReturn] forKey:@"stores"];

    // retrieve
    NSMutableArray *stores = [NSMutableArray new];
    NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
    NSData *dataRepresentingSavedArray = [currentDefaults objectForKey:@"stores"];
    if (dataRepresentingSavedArray != nil)
    {
        NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:dataRepresentingSavedArray];
        if (oldSavedArray != nil)
            stores = [[NSMutableArray alloc] initWithArray:oldSavedArray];
        else
            stores = [[NSMutableArray alloc] init];
    }

    if ([stores count] > 0) {
        NSMutableArray * annotations =  [[NSMutableArray alloc] init];
        for(int i = 0;i< [stores count]; i++){

            Store *store = [stores objectAtIndex: i];

            CLLocationCoordinate2D location;
            if(store.GeoLat != 0 && store.GeoLong != 0){
                location.latitude = store.GeoLat;
                location.longitude = store.GeoLong; //works 
                NSLog(@"Adding store: %@", store.Name); //DONT WORK!! <-- MAIN PROBLEM
            }
        }
    }

Feels like I tried everything but can't figure out how it works in the decode but not when in loop the array after I put it into a array.

Anyone have any ideas?

Aromatize answered 12/8, 2010 at 13:8 Comment(2)
Hey, I realize it's not to do with the question at hand, but just FYI. Beginning variable names with capital letters is against all the style guidelines.Salverform
In objective-c you ivars should have small caps on first letter and classes should have upper case on first letter... just a convention.Principalities
H
13

You're not retaining the properties in initWithCoder.

Name = [decoder decodeObjectForKey:@"Name"];

is not using the setter of the (retaining) property you've defined. You're just setting the ivar. That means you don't acquire ownership and it can be deallocated.

Here are two ways you can retain the properties in your case:

self.Name = [decoder decodeObjectForKey:@"Name"];
Name = [[decoder decodeObjectForKey:@"Name"] retain];
Hallucinogen answered 13/8, 2010 at 12:2 Comment(2)
amazing, SO rocks, and so do you :)Aurar
Good and richful explanation :) was just what i was also looking for :)Sosthina

© 2022 - 2024 — McMap. All rights reserved.