0

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

2 Answers 2

1

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;
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your input. I tried it with your sugestions but had no luck. The result is still the same. I forgot to mention, that I use garbage collection - but I think that you already assumed that.
0

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.

2 Comments

I did't post the encodeWithCoder implementaion because I think the problem can not be in this method. If it were there, then I wouldn't be able to see the right values in initWithCoder. But I added it to my question now.
Thank you very much for all your input. The main problem in my application was, that I did not implemented the multi-document-architecture in the correct way. That lead to wrong handling of the various window-instances. I have fixed that now - but still loose the values of my instance variables after reading them by initWithCoder. But I think the situation is quite different now. That for I will post this in a new question. Thank you again for all your affords!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.