为什么我不能通过setter初始化一个类?

时间:2010-05-02 21:13:49

标签: objective-c setter getter

如果我有一个名为Tires的自定义类:

#import <Foundation/Foundation.h>

@interface Tires : NSObject {
@private
     NSString *brand;
     int size;
}

@property (nonatomic,copy) NSString *brand;
@property int size;

- (id)init;
- (void)dealloc;

@end
=============================================

#import "Tires.h"

@implementation Tires

@synthesize brand, size;

- (id)init {
     if (self = [super init]) {
          [self setBrand:[[NSString alloc] initWithString:@""]];
          [self setSize:0];
     }
     return self;
}

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

@end

我在View Controller中合成了一个setter和getter:

#import <UIKit/UIKit.h>
#import "Tires.h"

@interface testViewController : UIViewController {
     Tires *frontLeft, *frontRight, *backleft, *backRight;
}

@property (nonatomic,copy) Tires *frontLeft, *frontRight, *backleft, *backRight;

@end

====================================

#import "testViewController.h"

@implementation testViewController

@synthesize frontLeft, frontRight, backleft, backRight;

- (void)viewDidLoad {
     [super viewDidLoad];
     [self setFrontLeft:[[Tires alloc] init]];
}
- (void)dealloc {
    [super dealloc];
}

@end

[self setFrontLeft:[[Tires alloc] init]] 回来后死亡。它编译得很好,当我运行调试器时它实际上一直通过Tires上的 init 方法,但一旦它返回它就会死掉并且视图永远不会出现。但是,如果我将 viewDidLoad 方法更改为:

- (void)viewDidLoad {
     [super viewDidLoad];
     frontLeft = [[Tires alloc] init];
}

它运作得很好。我可以放弃设置器并直接访问 frontLeft 变量,但我的印象是我应该尽可能多地使用setter和getter,从逻辑上看它似乎是 setFrontLeft 方法应该有效。

这引出了我的同事在这些方面不断提出的另一个问题(我们都是Objective-C的新手);如果你和那些设定者和吸气者在同一个班级,那么为什么要使用setter和getter。

2 个答案:

答案 0 :(得分:7)

您已将frontLeft声明为'copy'属性:

@property (nonatomic,copy) Tires *frontLeft, *frontRight, *backleft, *backRight;

分配给此属性时,通过调用对象的copy方法创建副本。这仅适用于支持NSCopying协议的对象(即实现copyWithZone:方法的对象)。由于您的Tires类没有实现此方法,因此会出现异常。

您可能希望将其更改为“保留”属性:

@property (nonatomic,retain) Tires *frontLeft, *frontRight, *backleft, *backRight;

有关属性声明的更多信息,请参阅the Objective C documentation on declared properties

答案 1 :(得分:1)

我看到的一个问题是:

- (void)viewDidLoad {
    [super viewDidLoad];
    [self setFrontLeft:[[Tires alloc] init]];
}

当您调用[Tires alloc]时,您将获得一个保留计数为1的对象。然后使用已合成的set方法,将保留计数颠倒为2.当您的对象完成Tire对象时,它会将保留计数减少到1,但轮胎永远不会被解除分配。我认为你应该使用:

[self setFrontLeft:[[[Tires alloc] init] autorelease]];