使用访问器方法设置iVars? [英] Using accessor methods to set iVars?

查看:107
本文介绍了使用访问器方法设置iVars?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最初,我在寻找pickerData的设置方式,并想我不知道为什么不能直接分配它(如METHOD_002),但后来我说我真的应该使用访问器方法而不是直接设置实例变量。我理解这正确地说,METHOD_001是一个更好的方法这样做?

  @property(nonatomic,retain)IBOutlet NSArray * pickerData ; 

METHOD_001

   - (void)viewDidLoad {
NSLog(@VIEW:Single ... Loaded);
NSArray * dataArray = [[NSArray alloc] initWithObjects:@A,@B,@C,nil];
[self setPickerData:dataArray];
[dataArray release];
[super viewDidLoad];
}

- (void)dealloc {
[pickerData release];
[super dealloc]
}

OR METHOD_002

   - (void)viewDidLoad {
NSLog(@VIEW:Single ... Loaded);
if(pickerData!= nil)[pickerData release];
pickerData = [[[NSArray alloc] initWithObjects:@A,@B,@C,nil] retain];
[super viewDidLoad];
}

- (void)dealloc {
[pickerData release];
[super dealloc]
}



EDIT_001:



首先我添加了nil值来终止NSArrays,来自CI总是忘记这一点,我的坏。另外你是对的,我没有说明在METHOD_002中的事实,pickerData可能已经设置,结果泄漏旧的对象。一旦你开始注意到这些问题并修复代码,它开始看起来像METHOD_001是最好的主意。或者直接使用属性直接作为Vladimir和eJames。

  self.pickerData = [NSArray arrayWithObjects:@A @B,@C,nil]; 



EDIT_002:



指针和注释,现在我将继续使用METHOD_001,我可以很容易地使用NSArrayWithObjects:但我想尽量保持内存使用低自己释放的东西自己尽快(不是那么重要,但是未来项目)我也喜欢self.pickerData的感觉,但我仍然不确定我对点符号的感觉,并已经尝试坚持旧样式的对象和消息可能的话。再次感谢您的帮助。



gary

解决方案

总是使用属性的访问器(在Objective-C 2.0中使用 self.property 符号。)



?因为它提供了自动访问控制和对象生命周期管理。生成的访问器可以提供很多保护,例如读/写,复制,保留等,否则需要很多手动代码。如果你编写自己的访问器,你可以添加所有的验证和副作用你想要的。



(在Objective-C 2.0写入访问器被视为高级艺术之前,如果你充分利用了潜力,还是可以的。)



你应该直接访问属性的时候是当你写一个访问器。例如采用这种常见的模式:

  @property(nonatomic,retain)NSMutableArray * myObjects; 
@synthesize myObjects;

- (NSMutableArray *)myObjects {
if(myObect!= nil){
return myObect;
}
NSMutableArray * anArray = [[NSMutableArray alloc] initWithCapacity:1];
self.myObject = anArray;
[anArray release]
return myObject;
}




  1. 此访问器确保myObjects永远不为nil在其余代码中删除了大量的样板nil测试。

  2. 你显然不能在访问器中调用 self.myObjects (这真的是[self myObjects]),而不创建一个无限递归所以你必须访问这里的原始变量,但...

  3. ...你可以调用(自动生成) self.myObjects = (这是真的[self setMyObjects:anArray]),因为它是一个完全不同的方法。如果你看看setMyObjects的内部:你会看到它访问原始变量。

  4. 如果您使用生成的访问器,则 self.myObjects = 会为您处理保留,复制, 。你只有调用release的时候是在dealloc。这个单独消除了人们在Objective-C中产生的一半错误。

相反,在访问器方法之外,通过直接访问类中的属性自己的方法。它所做的就是保存一些关键笔划,同时暴露你很难找到bug的风险。



如前面的答案所示,您通过尝试直接管理属性来产生了几个内存错误。如果你每次都使用访问器,你就不会有它们。例如:

  pickerData = [[[NSArray alloc] initWithObjects:@A,@B,@C ,nil] retain]; 

...必须正确管理每一次,而...

  self.pickerData = [[NSArray alloc] initWithObjects:@A,@B,@C,nil] 

...自动更正。



请记住,任何Objective-C类的最终设计目标都应该是完美的模块化和可重用的。这意味着它应该管理所有自己的内存,自己的数据验证和自己的副作用。访问者对于管理是至关重要的。通过围绕变量的每个访问包围逻辑,您可以确保(1)它是您期望的类型,范围等,并且(2)它总是在需要它的时候(3),你可以控制所有写入或读取变量的效果和(4)它不泄漏。



我无法充分发挥访问器的优点。事实上,我可能会写一首小歌。 ; - )


Initially, I was looking at the way "pickerData" is set and thinking I wonder why you can't just assign it directly (as in METHOD_002), but then I stated thinking that I should really be using the accessor methods I defined and not setting the instance variables directly. Am I understand this correctly that METHOD_001 is a better way of doing this?

@property(nonatomic, retain) IBOutlet NSArray *pickerData;

METHOD_001

-(void)viewDidLoad {
    NSLog(@"VIEW: Single ... Loaded");
    NSArray *dataArray = [[NSArray alloc] initWithObjects:@"A", @"B", @"C",nil];
    [self setPickerData:dataArray];
    [dataArray release];
    [super viewDidLoad];
}

-(void)dealloc {
    [pickerData release];
    [super dealloc];
}

OR METHOD_002

-(void)viewDidLoad {
    NSLog(@"VIEW: Single ... Loaded");
    if(pickerData != nil) [pickerData release];
    pickerData = [[[NSArray alloc] initWithObjects:@"A", @"B", @"C", nil] retain];
    [super viewDidLoad];
}

-(void)dealloc {
    [pickerData release];
    [super dealloc];
}

EDIT_001:

First off I have added the "nil" values to terminate the NSArrays, coming from C I always forget this, my bad. Also you're right, I did not account for the fact in METHOD_002 that pickerData might already be set and as a result leak the old object. Once you start noticing these problems and fixing the code it starts to look like METHOD_001 is the best idea. Or to just use the property directly as Vladimir and eJames noted.

self.pickerData = [NSArray arrayWithObjects: @"A", @"B", @"C", nil];

EDIT_002:

Thank you for all the pointers and comments, for now I am going to stick with METHOD_001, I could just as easily use NSArrayWithObjects: but I am trying to keep memory usage low by releasing things myself as soon as I can (not that it matters here, but for future projects) Also I do like the feel of self.pickerData, but I am still unsure how I feel about dot-notation and have for now been trying to stick with old style objects and messages where possible. Again many thanks for the help.

gary

解决方案

You should always use accessors of properties (which in Objective-C 2.0 means using the self.property notation.)

Why? Because it provides automatic access control and object life-cycle management. The generated accessors can provide a lot protection, such as read/write, copy, retain etc that take a lot of manual code otherwise. If you write your own accessors, you can add in all the validation and side effects you want.

(Back before Objective-C 2.0 writing accessors was considered a high art. It still can be if you fully exploit the potential.)

The only time you should access properties directly is when you are writing an accessor. For example take this common pattern:

@property(nonatomic, retain)  NSMutableArray *myObjects;
@synthesize myObjects;

-(NSMutableArray *) myObjects{
    if (myObect!=nil) {
        return myObect;
    }
    NSMutableArray *anArray=[[NSMutableArray alloc] initWithCapacity:1];
    self.myObject=anArray;
    [anArray release]
    return myObject;
}

  1. This accessor ensures that myObjects is never nil which removes a lot of boilerplate nil testing in the rest of your code.
  2. You obviously can't call self.myObjects (which is really [self myObjects] )inside the accessor without creating an infinite recursion so you must access the raw variable here but...
  3. ...You can call (the autogenerated) self.myObjects= (which is really [self setMyObjects:anArray] ) because it's an entirely different method. If you look at the internals of setMyObjects: you would see that it access the raw variable as well.
  4. If you use the generated accessors, self.myObjects= handles retaining, copying, nilling etc for you, every time you call it. The only time you have to call release is in the dealloc. This alone wipes out probably half the errors people make in Objective-C.

Conversely, outside of an accessor method, you gain absolutely nothing by directly accessing the properties inside the classes own methods. All it does is save some key strokes while exposing you to the risk of hard to find bugs.

As the previous answers demonstrated, you made several memory errors by trying to manage the property directly. Had you used the accessor every time, you would not have made them. For example:

pickerData = [[[NSArray alloc] initWithObjects:@"A", @"B", @"C", nil] retain];

... has to be managed exactly right every time whereas ...

self.pickerData = [[NSArray alloc] initWithObjects:@"A", @"B", @"C", nil];

... is automatically correct.

Remember that the ultimate design goal for any Objective-C class is that is should be perfectly modular and reusable. That means it should manage all its own memory, its own data validation and its own side effects. Accessors are absolutely vital to that management. By wrapping logic around every access of a variable, you ensure that (1) it is the type, range, etc you expect and (2) that it is always around when you need it be (3) that you can control all the side effects of writing or reading the variable and (4) that it doesn't leak.

I cannot extol the virtues of accessors enough. In fact, I might write a little song. ;-)

这篇关于使用访问器方法设置iVars?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆