如果我有一个名为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。
答案 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]];