NSCoding с помощью NSString внутри объекта - PullRequest
7 голосов
/ 12 августа 2010

Моя проблема заключается в том, что я получаю свой NSArray из Store объектов, все мои свойства NSString вызывают BadAccess ошибки. Int и double properties работают отлично!

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

Вот мой код для хранения и извлечения массива.

//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
            }
        }
    }

Такое ощущение, что я все перепробовал, но не могу понять, как это работает в декодере, но не в цикле массива после того, как я поместил его в массив.

У кого-нибудь есть идеи?

1 Ответ

12 голосов
/ 13 августа 2010

Вы не сохраняете свойства в initWithCoder.

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

не использует установщик указанного вами (сохраняющего) свойства.Вы просто устанавливаете ивар.Это означает, что вы не приобретаете право собственности, и оно может быть освобождено.

Вот два способа сохранить свойства в вашем случае:

self.Name = [decoder decodeObjectForKey:@"Name"];
Name = [[decoder decodeObjectForKey:@"Name"] retain];
...