2010-05-02 79 views
1

如果我有一个自定义类名为轮胎​​:为什么我不能通过setter初始化一个类?

#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 

我合成在我的视图控制器一个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 

它死后[自setFrontLeft:[轮胎页头] init]]回来。它编译得很好,当我运行调试器时,它实际上一直通过轮胎上的init方法,但一旦它回来,它就会死掉,视图永不会出现。但是,如果我改变viewDidLoad中方法:

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

它工作得很好。我可以直接抛弃setter并直接访问变量,但我的印象是,我应该尽可能地使用setter和getter,并且逻辑上看起来像setFrontLeft方法应该起作用。

这引发了一个额外的问题,我的同事们不断询问这些问题(我们都是Objective-C的新手);如果你和那些制定者和获得者在同一个班上,那么为什么要使用制定者和获得者呢?

+0

为什么在同一个班级中使用setter/getter?因为你的setter(以及更不常用的getter)可能不仅仅是分配值而是做其他事情,例如管理资源或更新其他实例变量。在类中直接访问变量意味着您必须复制该附加功能,否则将失去内部一致性。它打破封装。我相信在构造函数中没有使用综合属性方法是一个原则,因为它们可能没有完全建立 - 但是我没有充分理解构造函数如何失败。 – walkytalky 2010-05-02 22:11:55

回答

7

您已经声明frontLeft为“复制”属性:

@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

+0

完美的工作!我忘记了setter调用** copy **方法。标记为答案。 即使你和它们在同一个类中,为实例变量使用setter和getter也是常见的做法吗?我和我的合作开发者之间的讨论不断出现。 – Rob 2010-05-02 22:13:58

+0

我想你是否使用getters/setters主要是一个偏好问题。在这种情况下,我会使用setter,因为它会自动为您保留变量。我不会在课堂上使用getter。 – 2010-05-02 22:31:45

+0

使用setter可免费为您提供内存管理(假设您已正确设置属性),这在大多数情况下都是大赢家。如果我使用setter(在一个类中)使代码更加一致(因此更具可读性),我通常会使用getter。 – 2010-05-03 08:04:50

1

的一个问题,我看到的是在这里:

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

当你调用[轮胎页头]你回来的对象为1。保留计数,然后您可以使用您已经合成了一组方法,该方法将保留计数碰到2.当您的对象完成Tire对象时,它会将保留计数减少回1,但轮胎将永远不会被释放。我认为你应该使用:

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

尝试** [self setFrontLeft:[[[Tyres alloc] init] autorelease]]; **它仍然执行相同的操作。在调试器中,它表示** TERMINATING_DUE_TO_UNCAUGHT_EXCEPTION **,如果我运行该应用程序,它刚启动时就会崩溃。 – Rob 2010-05-02 21:45:35

相关问题