Почему я не могу инициализировать класс через сеттер? - PullRequest
1 голос
/ 03 мая 2010

Если у меня есть собственный класс с именем Tyres:

#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

И я синтезирую сеттер и геттер в моем контроллере вида:

#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: [[Tire alloc] init]] возвращается. Он прекрасно компилируется, и когда я запускаю отладчик, он на самом деле проходит через метод init в Tyres, но как только он возвращается, он просто умирает и представление никогда не появляется. Однако, если я изменю viewDidLoad метод на:

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

Работает просто отлично. Я мог бы просто бросить сеттер и получить доступ к переменной frontLeft напрямую, но у меня сложилось впечатление, что я должен использовать сеттеры и геттеры как можно чаще, и логически кажется, что setFrontLeft работа.

Это поднимает дополнительный вопрос, который мои коллеги продолжают задавать в этом отношении (мы все новички в Objective-C); зачем вообще использовать сеттер и геттер, если вы в одном классе с этими сеттерами и геттерами.

Ответы [ 2 ]

7 голосов
/ 03 мая 2010

Вы объявили frontLeft как свойство 'copy':

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

Когда вы присваиваете этому свойству, копия создается с помощью метода copy объекта. Это работает только для объектов, которые поддерживают протокол NSCopying (т.е. реализуют метод copyWithZone:). Поскольку ваш Tires класс не реализует этот метод, вы получаете исключение.

Возможно, вы захотите изменить это свойство на 'retain':

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

См. документацию Objective C по объявленным свойствам для получения дополнительной информации по объявлениям свойств.

1 голос
/ 03 мая 2010

Одна проблема, которую я вижу здесь:

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

Когда вы вызываете [Tire alloc], вы получаете объект с счетом сохранения 1. Затем вы используете синтезированный метод, который увеличивает значение сохранения до 2. Когда ваш объект сделан с объектом Tire , это уменьшит счет удержания обратно до 1, но шина никогда не будет освобождена. Я думаю, что вы должны использовать:

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