2010-05-02 63 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

相關問題