2010-03-01 79 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 

这编译就好了。我想用它的“addCard”方法初始化一个“DeckCards”实例52次。当我在DeckCards setter方法中调用addCard 52次并询问其“cardSet”的大小时,我返回0.

这似乎是一个范围或特权问题? “addCard”方法是否具有setter特权?必须使用setter参数与返回和相应的成员类型相同?

[我可以通过在“DeckCard”之外创建一个NSMutableArray对象“deck_cards_temp”来解决上述问题,向其中添加52张卡片,并通过setter继承“DeckCards” CardSet”。这是不是很满意!]

你有什么建议?非常感谢您的帮助和耐心。

+0

你或许应该还显示'DeckCards'源。 – 2010-03-01 01:53:54

+0

请注意,您可以通过缩进4个空格或单击* code *按钮来创建代码块。 – 2010-03-01 01:57:05

+1

您还应该将这些访问器方法重命名为符合KVC。有关完整列表,请参阅http://developer.apple.com/documentation/Cocoa/Conceptual/ModelObjects/Articles/moAccessorMethods.html;两个你应该改变'getCardSet'(应该只是'cardSet')和'getCard:'(应该是'objectInCardSetAtIndex:')。如果有任何事情(包括未来某天)会观察这个'cardSet'属性,这将为这些访问器启用自动KVO通知。 – 2010-03-01 02:04:43

回答

3

你永远不会实际创建cardSet对象。你应该在你-init方法来创建它:

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

因为你从来没有真正创建磁盘阵列,所有-addCard:的呼叫被发送给nil对象。

当您将一个数组传递给-setCardSet:时,您传递的是初始化数组,因此该数组不再为零,并且-addCard:调用正常工作。

+0

感谢您的回复。这实际上在脚本中有一定的评论 - 我不认为你需要在init中实例化NSMutableArray,XCode只是告诉我该数组未被使用。我也说过,将一个数组传递给setter可以很好地工作,但它没有吸引力。 – SK9 2010-03-01 06:49:39

+0

其实你说的有点不同......我会检查出来的,你可能是对的! – SK9 2010-03-01 07:30:42

+0

如果你想使用它,你肯定需要实例化这个数组。在你为cardSets实例变量赋值一个有效数组之前,它的值是'nil',所有到'nil'的消息都被忽略。其他一些答案提供了有关改进实施的信息,但缺乏初始化是您问题的核心。 – 2010-03-01 22:27:08

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答案的评论中指出的那样,在初始化方法中设置实例变量的值时,不应该使用访问器。直接设置,就像我的答案一样。 – 2010-03-01 22:29:47

+0

哦,你是对的。感谢您指出了这一点。那么这是否意味着访问器没有在init方法中正确设置?什么时候使用它们是安全的? – bddckr 2010-03-02 11:09:24

0

我会缩短该init方法:

- (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

您通常应该避免在初始化器中使用存取器方法。只需直接设置伊娃。 – 2010-03-01 22:28:12