Arno
Arno

Reputation: 447

Values (int, struct-values) from initWithCoder are lost outside this method

I am quite new to objective-c and got stuck with a quite simple task I assume. I use Xcode 4.0.1 and my deployment target is OS X 10.6.

I save and load some plain C ints s and struct values by using encodeWithCoder and initWithCoder. This works quite good - the saved values are loaded and I can NSLog them in the initWithCoder method.

But when I want to use these loaded values in an other method, they are all gone. But I can not see why or where the values are lost.

Here are the relevant parts of my code:

My Header file:

@interface OptimiererZwoAppDelegate : NSDocument <NSApplicationDelegate,NSCoding> {

//Winkel in Grad
__strong struct bildanalyse { 
    float winkelo;
    float winkelr;
    ... here are some more variables…
    float skalfak;   
};

__strong struct bildanalyse *analyse;
__strong int16_t anzahlanalysewerte;


...some more stuff....
}
...
- (NSData *) dataOfType:(NSString *)aType error:(NSError **)outError;
- (BOOL) readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError;
- (void) encodeWithCoder: (NSCoder *) coder;
- (id) initWithCoder: (NSCoder *) coder;
...

@property __strong struct bildanalyse *analyse;
@property __strong int16_t anzahlanalysewerte;
...

And this is my implementation file:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    ...some code...
    [self prepareApp]; 
}


-(void) prepareApp{
    NSLog(@"prepareApp");
    self.analyse = NSAllocateCollectable(sizeof(struct bildanalyse) * 256, 0); 
    self.anzahlanalysewerte = 0;
}


- (void) encodeWithCoder: (NSCoder *) coder{

    [coder encodeInt:self.anzahlanalysewerte forKey: @"anzahlanalysewerte"];

    for(int i=0; i< self.anzahlanalysewerte; i++){
        [coder encodeFloat:self.analyse[i].winkelo forKey: [NSString stringWithFormat:@"winkelo%d",i]];
        [coder encodeFloat:self.analyse[i].winkelr forKey: [NSString stringWithFormat:@"winkelr%d",i]];
        ...
        [coder encodeFloat:self.analyse[i].skalfak forKey: [NSString stringWithFormat:@"skalfak%d",i]];
    }
}

- (id) initWithCoder: (NSCoder *) coder{
    self = [super init];
    [self prepareApp]; 
    self.anzahlanalysewerte = [coder decodeIntForKey:@"anzahlanalysewerte"];

    for(int i=0; i< self.anzahlanalysewerte; i++){
        self.analyse[i].winkelo = [coder decodeFloatForKey: [NSString stringWithFormat:@"winkelo%d",i]];
        self.analyse[i].winkelr = [coder decodeFloatForKey: [NSString stringWithFormat:@"winkelr%d",i]];
        ...
        self.analyse[i].skalfak = [coder decodeFloatForKey: [NSString stringWithFormat:@"skalfak%d",i]];
    }
    return self;
}

Upvotes: 0

Views: 573

Answers (2)

Rob Keniger
Rob Keniger

Reputation: 46020

You can't use Objective-C dot syntax to set the value of struct members if you are referring to the struct itself via dot syntax as an Objective-C property. In fact, the compiler should warn you about this.

To illustrate, if foo is a struct with a member bar, you cannot do this:

anObjCobject.foo.bar = 42;

However, you can assign an entire struct to the property like this:

foobar.bar = 42; // where foobar is a struct of the same type as foo
anObjCobject.foo = foobar;

The confusion probably stems from the fact that you can access the value of a struct member that is a property of an Objective-C object using dot notation:

NSLog("%lu", anObjCobject.foo.bar); //outputs 42, perfectly legal

It's just setters that are the problem, getters work fine with dot notation.

Also, you should also avoid using accessors in ‑init methods, you should instead set the ivars directly.

You will need to end up with something like this:

- (id) initWithCoder: (NSCoder *) coder{
    if((self = [super init]))
    {
        [self prepareApp]; 
        anzahlanalysewerte = [coder decodeIntForKey:@"anzahlanalysewerte"];

        //self.analyse needs to be malloc'd to accomodate the size of anzahlanalysewerte as well
        for(int i=0; i< self.anzahlanalysewerte; i++)
        {

            bildanalyse foo;
            foo.winkelo = [coder decodeFloatForKey: [NSString stringWithFormat:@"winkelo%d",i]];
            foo.winkelr = [coder decodeFloatForKey: [NSString stringWithFormat:@"winkelr%d",i]];
            ...
            foo.skalfak = [coder decodeFloatForKey: [NSString stringWithFormat:@"skalfak%d",i]];

            analyse[i] = foo;
        }
    }
    return self;
}

Upvotes: 1

Joe
Joe

Reputation: 57179

Where is your - (void)encodeWithCoder:(NSCoder *)encoder implementation? If you did not implement it that is probably your problem, if you did implement it please post that as well. Also you are trying to access a struct pointer directly so you should make sure self is not nil in initWithCoder:.

- (id) initWithCoder: (NSCoder *) coder{
    if((self = [super init]))
    {
        [self prepareApp]; 
        self.anzahlanalysewerte = [coder decodeIntForKey:@"anzahlanalysewerte"];

        //self.analyse needs to be malloc'd to accomodate the size of anzahlanalysewerte as well
        for(int i=0; i< self.anzahlanalysewerte; i++){
            self.analyse[i].winkelo = [coder decodeFloatForKey: [NSString stringWithFormat:@"winkelo%d",i]];
            self.analyse[i].winkelr = [coder decodeFloatForKey: [NSString stringWithFormat:@"winkelr%d",i]];
            ...
            self.analyse[i].skalfak = [coder decodeFloatForKey: [NSString stringWithFormat:@"skalfak%d",i]];
        }
    }
    return self;
}

Note: When you conform to a protocol you do not need to add the methods of that protocol to the header file. You can safely remove both - (void) encodeWithCoder: (NSCoder *) coder; and - (id) initWithCoder: (NSCoder *) coder; from the header.

Upvotes: 0

Related Questions