【问题标题】:Values (int, struct-values) from initWithCoder are lost outside this methodinitWithCoder 中的值(int,struct-values)在此方法之外丢失
【发布时间】:2011-08-15 15:15:33
【问题描述】:

我对 Objective-c 很陌生,并且被我假设的一个非常简单的任务困住了。我使用 Xcode 4.0.1,我的部署目标是 OS X 10.6。

我使用encodeWithCoderinitWithCoder 保存并加载了一些普通的C ints 和结构值。 这非常有效 - 保存的值已加载,我可以在 initWithCoder 方法中 NSLog 它们。

但是当我想在其他方法中使用这些加载的值时,它们都消失了。但我看不出价值丢失的原因或位置。

以下是我的代码的相关部分:

我的头文件:

@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;
...

这是我的实现文件:

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

【问题讨论】:

    标签: objective-c cocoa osx-snow-leopard


    【解决方案1】:

    如果您通过点语法将结构本身作为 Objective-C 属性引用,则不能使用 Objective-C 点语法来设置结构成员的值。事实上,编译器应该警告你这一点。

    为了说明,如果foo 是一个带有成员bar 的结构,你不能这样做:

    anObjCobject.foo.bar = 42;
    

    但是,您可以像这样将整个结构分配给属性:

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

    混淆可能源于您可以使用点符号访问作为Objective-C对象属性的结构成员的值:

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

    问题出在 setter 上,getter 在点符号下工作得很好。

    另外,您还应该避免在 ‑init 方法中使用访问器,而应该直接设置 ivars。

    你需要得到这样的结果:

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

    【讨论】:

    • 感谢您的意见。我用你的建议试过了,但没有运气。结果还是一样。我忘了提,我使用垃圾收集 - 但我认为你已经假设了。
    【解决方案2】:

    您的- (void)encodeWithCoder:(NSCoder *)encoder 实施在哪里?如果您没有实现它,那可能是您的问题,如果您确实实现了它,请也发布它。此外,您正在尝试直接访问结构指针,因此您应该确保 initWithCoder: 中的 self 不为零。

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

    注意:当你遵守一个协议时,你不需要将该协议的方法添加到头文件中。您可以安全地从标题中删除 - (void) encodeWithCoder: (NSCoder *) coder;- (id) initWithCoder: (NSCoder *) coder;

    【讨论】:

    • 我没有发布 encodeWithCoder 实现,因为我认为问题不可能出在这种方法上。如果它在那里,那么我将无法在 initWithCoder 中看到正确的值。但我现在将其添加到我的问题中。
    • 非常感谢您的所有意见。我的应用程序中的主要问题是,我没有以正确的方式实现多文档架构。这会导致对各种窗口实例的错误处理。我现在已经解决了这个问题 - 但在通过 initWithCoder 读取实例变量后仍然会丢失它们的值。但我认为现在的情况已经完全不同了。因为我将在一个新问题中发布这个。再次感谢您的付出!
    猜你喜欢
    • 1970-01-01
    • 2018-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-26
    • 1970-01-01
    • 2013-04-12
    相关资源
    最近更新 更多