2011-07-01 27 views
2

当执行错误: “无法识别的选择” 使用addObjects时:对一个NSMutableArray

[self.blockViews addObject:curBlockView]; 

我得到一个错误

2011-07-01 13:35:26.240 Block Breaker[42061:207] -[__NSArrayI addObject:]: unrecognized selector sent to instance 0x4e037a0

我非常新的Objective-C的。这是否在我的init方法中?

// 
// GameEngine.h 
// Block Breaker 
// 
// Created by Chris Muench on 7/1/11. 
// Copyright 2011 N/A. All rights reserved. 
// 

#import <Foundation/Foundation.h> 


@interface GameEngine : NSObject { 
    NSMutableArray *blockViews; 
    int numBlockRows; 
    int score; 
} 
@property (nonatomic, copy) NSMutableArray *blockViews; 
@property int numBlockRows; 
@property int score; 

- (void) setup; 
- (void) setupBlocks; 
@end 


// 
// GameEngine.m 
// Block Breaker 
// 
// Created by Chris Muench on 7/1/11. 
// Copyright 2011 N/A. All rights reserved. 
// 

#import "GameEngine.h" 
#import "Block.h" 
#import "BlockView.h" 


@implementation GameEngine 
@synthesize blockViews; 
@synthesize numBlockRows; 
@synthesize score; 

- (id) init 
{ 
    if ((self = [super init])) 
    { 
     self.blockViews = [[NSMutableArray alloc] init]; 
     self.numBlockRows = 2; 
     self.score = 0; 
    } 
    return self; 
} 

- (void) setup 
{ 
    [self setupBlocks]; 
} 

- (void) setupBlocks 
{ 
    float blockWidth = 10; 
    float blockHeight = 10; 
    float rowSpacing = 2; 
    float colSpacing = 2; 
    float currentX = 0; 
    float currentY=10; 
    float screenWidth = 200; 

    for (int rowCounter=0;rowCounter<self.numBlockRows;rowCounter++) 
    { 

     while(currentX <=screenWidth) 
     { 
      Block *curBlock = [[Block alloc] initWithWidth:blockWidth height:blockHeight]; 
      BlockView *curBlockView = [[BlockView alloc] initWithFrame:CGRectMake(currentX, currentY, curBlock.width, curBlock.height)]; 
      curBlockView.block = curBlock; 

      [self.blockViews addObject:curBlockView];   
      currentX+=blockWidth+colSpacing; 
      [curBlock release]; 
      [curBlockView release]; 
     } 

     currentX=0; 
     currentY+=blockHeight+rowSpacing; 
    } 


} 

@end 
+0

看来,如果我改变@property(nonatomic,copy)NSMutableArray * blockViews,保留,错误消失。但为什么? –

+0

再次考虑,在许多情况下,您不需要设置可变数组。该数组是可变的,这就是为什么你只需要“访问”它的指针来添加新的对象。除此之外,你不需要在'init'中使用setter。你可以直接在那里引用ivars。 – sidyll

+2

你不想做self.blockviews = [[NSMutableArray alloc] init];不管下面人们回答的复制/保留问题如何。你最终会泄漏内存。使用blockViews = [[NSMutableArray alloc] init];或self.blockViews = [NSMutableArray数组]; – InsertWittyName

回答

10

当使用copy方法,或用于该属性被指定为copy合成设定器复制NSMutableArray,则得到一个不可改变拷贝,这意味着你基本上与纯NSArray结束。*有一种方法mutableCopy将保留可变性,但我不相信有任何方法可以指定一个属性。

如果你希望你的数组在你设置的时候被可变地复制,你必须编写你自己的setter方法,并在属性声明中指定该方法。

@property (nonatomic, copy, setter=setBlockViewsByCopying) NSMutableArray * blockViews; 

- (void) setBlockViewsByCopying: (NSMutableArray *)newBlockViews { 
    NSMutableArray * tmp = [newBlockViews mutableCopy]; 
    [blockViews release]; 
    blockViews = tmp; 
} 

一个侧面说明,作为@InsertWittyName在评论中提到,你的代码初始化blockViews会造成泄漏,因为你要创建的阵列上所有权的两种说法 - 一个用于alloc,一个用于retaincopy你开始使用性质:

self.blockViews = [[NSMutableArray alloc] init]; 
//^One claim     ^Two claims 
// Only one release later, when the property is set again! 
// LEAK! 

而应该做的事:

self.blockViews = [NSMutableArray array]; 
// Creates an object you don't own which you then make one claim 
// on using the setter 

*虽然,因为它是一类集群,你真的得到一些未指明具体的子类。

-1

您是否retain您的数组?

0

复制应该保留,如果我没有记错的话。

无论如何,使用复制不能达到最佳效果,每次调用访问器(set)时,都会得到一份副本,并且如上所述,它是不可变的。

添加很好,但记得在完成时释放数组。

相关问题