objective-c的属性声明问题“ivar used by '@synthesize' declaration must be an existing iva”

来源:互联网 发布:马尔可夫链的算法 编辑:程序博客网 时间:2024/05/22 01:54
在GNU环境中,测试一段objective-c的代码。很简单一个数据类,定义了一些属性和一个初始化方法,如下所示:

#import <Foundation/Foundation.h>

@interface CtripSign:NSObject
@property (nonatomic,copy) NSString * allianceID;
@property (nonatomic,copy) NSString * apiKey;
@property (nonatomic,copy) NSString * siteID;
@property (nonatomic,copy) NSNumber * timestamp;
@property (nonatomic,copy) NSString * requestType;
@property (nonatomic,copy) NSString * sign;
-(id)initWithallicanceID:(NSString *)allianceID apiKey:(NSString *)apiKey  siteID:(NSString *)siteID timestamp:(NSNumber *) timestamp requestType: (NSString *) requestType;
@end

#import "CtripSign.h"
#import "CtripDefine.h"
#import "NSString+Exts.h"

@implementation CtripSign
@synthesize allianceID=_allianceID;
@synthesize apiKey=_apiKey;
@synthesize siteID=_siteID;
@synthesize timestamp=_timestamp;
@synthesize requestType=_requestType;
@synthesize sign=_sign;

-(id)initWithallicanceID:(NSString *)allianceID apiKey:(NSString *)apiKey  siteID:(NSString *)siteID timestamp:(NSNumber *) timestamp requestType: (NSString *) requestType
{
    self = [super init];
    if (self) {
        _allianceID = allianceID;
        _apiKey = apiKey;
        _siteID = siteID;

        long long int timeStampNum=0;
        if (timestamp == nil)
        {
            // NSTimeInterval is defined as double
            timeStampNum = (long long int)[[NSDate date] timeIntervalSince1970];
            _timestamp=[NSNumber numberWithLongLong:timeStampNum];

        }
        else
        {
        _timestamp=timestamp;
        }

        _requestType=requestType;

        NSString *timestampStr=  [NSString stringWithFormat:@"%lld",timeStampNum];

        NSString *signatureCtrip=[timestampStr stringByAppendingString:allianceID];

        signatureCtrip=[signatureCtrip stringByAppendingString:[[_apiKey md5] uppercaseString]];
        signatureCtrip=[signatureCtrip stringByAppendingString:_siteID];
        signatureCtrip=[signatureCtrip stringByAppendingString:_requestType];

        signatureCtrip=[signatureCtrip md5];
        signatureCtrip=[signatureCtrip uppercaseString];

        _sign=signatureCtrip;

        return self;
    }
    return nil;
}

@end

这个类,我在apple机器上xcode4.5上调试是可以通过的,但是在gnu上调试却不行,报错如下:
E:\GNUStep\stanford2013\ctrip\CtripSign.m|16|error: ivar 'allianceID' used by '@synthesize' declaration must be an existing ivar|

我想,或许是版本问题,这个错误是说应该在CtripSign.h文件中应先添加变量声明。于是将CtripSign.h修改成这样
@interface CtripSign:NSObject
{
@property (nonatomic,copy) NSString * allianceID;
@property (nonatomic,copy) NSString * apiKey;
@property (nonatomic,copy) NSString * siteID;
@property (nonatomic,copy) NSNumber * timestamp;
@property (nonatomic,copy) NSString * requestType;
@property (nonatomic,copy) NSString * sign;
}
@property (nonatomic,copy) NSString * allianceID;
...........

@end

再编译,还是不过。后来想起来变量名称应该是以下划线开始,这才是类的私有变量的声明方式,而且我在类实现代码中就是这样调用的,如_allianceID

后来google到网友HoNooD的一文http://blog.csdn.net/g5dsk/article/details/6623099

他给出的解释是这样。

1、在 32-bit 时,如果类的 @interface 部分没有进行 ivar 声明,但有 @property 声明,在类的 @implementation 部分有相应的 @synthesize,则会得到类似下面的编译错误:  
Synthesized property 'xX' must either be named the same as a compatible ivar or must explicitly name an ivar  

2、在 64-bit时,运行时系统会自动给类添加 ivar,添加的 ivar 以一个下划线"_"做前缀。  
上面声明部分的 @synthesize window=_window; 意思是说,window 属性为 _window 实例变量合成访问器方法。  

我在xcode 4.5上编辑没问题,但在gnu上编译出错。前者是64-bit,而后者是一个PC机,32-bit。