我们使用 @property 关键字声明属性,并在实现文件中合成它。我的问题是,
如果我使用@property关键字声明属性并且在接口块中使用相同的名称声明变量,该怎么办?例如,请考虑以下代码,
接口:
@interface myClass : NSObject {
NSString *myClass_name; // LINE 1
}
@property(nonatomic, retain) NSString *myClass_name; // LINE 2
@end
实现:
@implementation myClass
@synthesize myClass_name // LINE 3
@end
在LINE 1中声明myClass_name会出现任何问题吗?像任何参考问题或任何不必要的内存消耗问题?
答案 0 :(得分:3)
不,实际上,声明这样的属性需要它。您可以将声明替换为:
@interface MyClass : NSObject {
NSString *ivar;
}
@property (nonatomic, retain) NSString *myClass_name;
@end
然后将您的实施更改为
@implementation MyClass
@synthesize myClass_name = ivar;
@end
(如果你没有指定= some_ivar,它将假定ivar与属性具有相同的名称。)
您总是需要以下几行:
合成属性时,如果未指定要使用的ivar(最后使用=ivar
),则会假定有一个与属性同名的ivar。
答案 1 :(得分:1)
声明属性并合成它不会在您的情况下产生任何参考问题。 这样做会为您的类中的实例变量创建访问器和setter方法。 如果属性中的变量名称和类中声明的变量名称,则xcode将两者都称为单个变量。
第3行和第4行是必须的。第1行是选项
答案 2 :(得分:1)
我从Apple的Declared Properties文档中获得了以下内容。我在这里发布它,以便将来可能对某人有所帮助。
运行时差异
通常,属性的行为在所有运行时都是相同的(请参阅Runtime Versions and Platforms中的Objective-C Runtime Programming Guide)。有一个关键区别:现代运行时支持实例变量合成,而遗留运行时则不支持。
要使@synthesize
在遗留运行时中工作,您必须提供具有相同名称和属性的兼容类型的实例变量,或者在@synthesize
语句中指定另一个现有实例变量。对于现代运行时,如果您不提供实例变量,编译器会为您添加一个。例如,给定以下类声明和实现:
@interface MyClass : NSObject {
float sameName;
float otherName;
}
@property float sameName;
@property float differentName;
@property float noDeclaredIvar;
@end
@implementation MyClass
@synthesize sameName;
@synthesize differentName=otherName;
@synthesize noDeclaredIvar;
@end
遗留运行时的编译器会在@synthesize noDeclaredIvar;
生成错误,而现代运行时的编译器会添加一个实例变量来表示noDeclaredIvar
。
答案 3 :(得分:1)
以下是面向对象的方式:
DeclaringProperties.h
@interface DeclaringProperties : NSObject
// ivars and {} can be omitted
@property (nonatomic, readwrite, retain) NSString *normal;
@property (nonatomic, readwrite, retain) NSString *alias;
@property (nonatomic, readonly, retain) NSString *readonly;
- (id) initWithNormal:(NSString *)aNormal alias:(NSString *)alias;
@end
DeclaringProperties.m
#import "DeclaringProperties.h"
// private interface
@interface DeclaringProperties ()
@property (nonatomic, readwrite, retain) NSString *readonly; // readwrite for self
@property (nonatomic, readwrite, retain) NSString *private;
@property (nonatomic, readwrite, retain) NSString *retain;
@end
#pragma mark -
@implementation DeclaringProperties
@synthesize normal, alias = _alias, readonly, private, retain;
// You can not use "normal" here;
// But you can still use "alias", and it is highlighted in XCode!
- (id) initWithNormal:(NSString *)aNormal alias:(NSString *)alias {
self = [super init];
if (self) {
self.normal = aNormal;
self.alias = alias;
self.readonly = @"readonly";
self.private = @"private";
// allocated(copied) variable for retained(copied) property should be released or autoreleased
NSString *alloc = [[NSString alloc] init];
self.retain = alloc;
[alloc release];
// or
self.retain = [[NSString alloc] init];
[self.retain release];
// or
self.retain = [[[NSString alloc] init] autorelease];
// I don't like ;)
retain = [[NSString alloc] init];
}
return self;
}
- (void) dealloc {
self.normal = nil;
self.alias = nil;
self.readonly = nil;
self.private = nil;
self.retain = nil;
[super dealloc];
}
@end