2010-03-01 3 views
1

У меня есть класс под названием «CardSet», содержащий NSMutableArray * cardSet для хранения «карт», которые я расширяю, чтобы сделать «DeckCards». Я бы хотел, чтобы «CardSet» имел метод «(void) addCard: (Card *)» (и аналогичным образом метод «removeCard»). Я хотел бы добавить «addCard» к некоторым способам доступа и установки CardSet. Еще лучше я хотел бы использовать метод «addCard» для инициализации cardSet. Файл класса "CardSet.h" гласит:Objective-C :: использование метода для изменения объекта

#import <Cocoa/Cocoa.h> 

#import <Card.h> 

@interface CardSet : NSObject { 

    NSMutableArray* cardSet; 

} 

-(id)init; 

-(NSMutableArray*)getCardSet; 

-(void)setCardSet:(NSMutableArray *)new_cardset; 

-(Card*)getCard:(NSInteger) index; 

**-(void)addCard:(Card*) new_card;** 

-(void)removeCard:(Card*) old_card; 

-(void)dealloc; 

@property (readwrite, retain, getter=getCardSet, setter=setCardSet) NSMutableArray* cardSet; 

@end 

и файл метод читает:

#import "CardSet.h" 

@implementation CardSet 

-(id)init{ 
    if(self = [super init]){} //will add initialisations here later 
    return self; 
} 

-(NSMutableArray*)getCardSet{ 
    return cardSet; 
} 

-(void)setCardSet:(NSMutableArray *)new_cardSet{ 
    cardSet = new_cardSet; 
} 

-(Card*)getCard:(NSInteger)index{ 
    return [cardSet objectAtIndex:index]; 
} 

**-(void)addCard:(Card *)new_card{ 
    [cardSet addObject:new_card]; 
}** 

-(void)removeCard:(Card *)old_card{ 
    [cardSet removeObject:old_card]; 
} 

-(void)dealloc{ 
    [cardSet release]; 
    [super dealloc]; 
} 

@synthesize cardSet; 

@end 

Это компилируется нормально. Я хотел бы инициализировать экземпляр «DeckCards», используя его метод «addCard» 52 раза. Когда я вызываю addCard 52 раза в методе setter DeckCards и запрашиваю размер его «cardSet», я возвращаюсь 0.

Это проблема с областью или привилегиями? Может ли метод «addCard» иметь какие-либо привилегии setter? Должен ли параметр setter быть таким же, как возвращаемый и соответствующий тип члена?

[Я могу обойти выше, создав объект NSMutableArray «deck_cards_temp» за пределами «DeckCard», добавьте к нему 52 карты и передайте его, чтобы установить член моего экземпляра «DeckCards» через установщик, унаследованный от " CardSet». Это не очень хорошо!]

Что вы посоветуете? Большое спасибо за вашу помощь и терпение.

+0

Вы, вероятно, следует также показать источник для 'DeckCards'. –

+0

Обратите внимание, что вы создаете кодовые блоки, отступы на 4 пробела или нажав кнопку * code *. –

+1

Вы должны также переименовать эти методы доступа как KVC-совместимые. Для получения полного списка см. Http://developer.apple.com/documentation/Cocoa/Conceptual/ModelObjects/Articles/moAccessorMethods.html; два, которые вы должны изменить: 'getCardSet' (должно быть просто' cardSet') и 'getCard:' (должно быть 'objectInCardSetAtIndex:'). Это позволит автоматическое уведомление KVO для этих устройств доступа, если что-либо когда-либо (включая когда-нибудь в будущем) наблюдает за этим свойством 'cardSet'. –

ответ

3

Вы никогда не создаете объект cardSet. Вы должны создать его в методе -init:

-(id)init 
{ 
    if(self = [super init]) 
    { 
     cardSet = [[NSMutableArray alloc] init]; 
    } 
    return self; 
} 

Потому что вы никогда на самом деле создать массив, все вызовы к -addCard: направляются к нулевому объекту.

Когда вы передаете массив в -setCardSet:, вы передаете инициализированный массив, поэтому массив больше не равен нулю, а вызовы -addCard: работают нормально.

+0

Спасибо за ответ. На самом деле это фактически комментируется в скрипте - я не думаю, что вам нужно создать экземпляр NSMutableArray в init, XCode просто говорит мне, что массив не используется. Я также заметил, что передача массива в сеттер работает отлично, но это непривлекательно. – SK9

+0

На самом деле вы говорите немного по-другому ... Я проверю это, вы, наверное, правы! – SK9

+0

Вам определенно нужно создать экземпляр массива, если вы хотите его использовать. Пока вы не присвоите действительный массив переменной экземпляра 'cardSets', его значение будет' nil', и все сообщения в 'nil' будут проигнорированы. Некоторые из других ответов предоставили информацию об улучшении вашей реализации, но отсутствие инициализации является ядром вашей проблемы. –

0

CardSet.h

#import <Cocoa/Cocoa.h> 

// For know we just need to know there is a class named "Card" being used but implemented later 
@class Card; 

@interface CardSet : NSObject { 
    NSMutableArray *cardSet; 
} 

// Here are the methods according to "correct" naming conventions 
- (Card *)cardAtIndex:(NSInteger)index; 
- (void)addCard:(Card *)card; 
- (void)removeCard:(Card *)card; 

// This will help us and forget about writing the setter/getter 
@property (nonatomic, retain) NSMutableArray *cardSet; 

@end 

CardSet.m

#import "CardSet.h" 
// Now we tell the compiler what "Card" is and what methods etc. it has 
#import "Card.h" 

@implementation CardSet 

@synthesize cardSet; 

- (id)init { 
    if (self = [super init]) { 
     // If we don't create the cardSet, how are we able to work with it!? 
     NSMutableArray *anArray = [[NSMutableArray alloc] init]; 
     self.cardSet = anArray; 
     [anArray release]; 
    } 
    return self; 
} 

- (Card *)cardAtIndex:(NSInteger)index { 
    return [cardSet objectAtIndex:index]; 
} 

- (void)addCard:(Card *)card { 
    [cardSet addObject:card]; 
} 

- (void)removeCard:(Card *)card { 
    [cardSet removeObject:card]; 
} 

- (void)dealloc { 
    [cardSet release]; 
    [super dealloc]; 
} 

@end 

Как Abizern уже отмечалось: Именование массив такой же, как ваш класс плохо.

+0

Как отмечалось в моем комментарии к ответу NSResponder, вы не должны использовать accessors при установке значения переменной экземпляра в методе инициализации. Просто установите его прямо, как в моем ответе. –

+0

О, ты прав. Спасибо что подметил это. Значит ли это, что аксессоры неправильно настроены в методе init? Когда именно безопасно их использовать? – bddckr

0

Я бы сократить этот метод инициализации:

- (id)init { 
    if (self = [super init]) { 
     // If we don't create the cardSet, how are we able to work with it!? 
     self.cardSet = [NSMutableArray array]; 
    } 
    return self; 
} 
+0

Обычно вам следует избегать использования методов доступа в инициализаторах. Просто установите ivar напрямую. –

Смежные вопросы