1

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

#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

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

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

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

这带来了一个额外的问题,我的同事在这些方面一直在问(我们都是 Objective-C 的新手);如果您与那些 setter 和 getter 属于同一类,为什么还要使用 setter 和 getter。

4

2 回答 2

7

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

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

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

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

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

有关属性声明的更多信息,请参阅关于声明属性的 Objective C 文档

于 2010-05-02T22:08:47.123 回答
1

我看到的一个问题是:

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

当您调用 [Tires alloc] 时,您会返回一个保留计数为 1 的对象。然后您使用已合成的 set 方法,将保留计数增加到 2。当您的对象使用完轮胎对象后,它将将保留计数减少回 1,但轮胎永远不会被释放。我认为你应该使用:

[self setFrontLeft:[[[Tires alloc] init] autorelease]];
于 2010-05-02T21:19:06.460 回答