Objective-C中的强制转换无法按预期工作

时间:2012-11-09 16:17:14

标签: objective-c casting nsmutablearray

我是使用Objective-C和Stackoverflow进行编程的新手,我需要一些帮助。

我正在尝试从NSMutableArray获取一个对象并检查其内部属性之一。我认为最好的方法是做以下演员:

GenericRoom *room = (GenericRoom*)[myRooms objectAtIndex: currentIndex + side];

if (room.myType == EMPTY) {
    return YES;
}

问题在于,当我创建GenericRoom类型的类时,构造函数已经将myType定义为EMPTY。当我在NSMutrableArray中插入实例时,我用这种方式改为myType TAVERN:

NSMutableArray *myRooms = [[NSMutableArray alloc] initWithCapacity:15];

for (int i = 0: i <15: i + +) {
    GenericRoom tmpRoom * = [[GenericRoom alloc] initWithType: TAVERN];
    myRooms insertObject: tmpRoom atIndex i];
}

但是当我在那里引用它时,它只是创建一个对象GenericRoom的新实例,而不是复制NSMutableArray中的对象,使其结果始终为YES,我的失败vereficação。

有没有更好的方法来解决这个问题? 谢谢大家。

编辑:完整的代码

GenericRoom.h

#import <Foundation/Foundation.h>
#import "cocos2d.h"

enum Rooms {
    EMPTY, TAVERN, WARRIORGUILD, MAGEGUILD
}roomsType;

@interface GenericRoom : CCLayer {
    CCSprite *mySprite;
    enum Rooms myType;
}

@property (nonatomic, retain) CCSprite *mySprite;
@property enum Rooms myType;
@property int test;

- (id)initWithSprite: (NSString *)file;
- (id)initWithType: (enum Rooms)roomType;

@end

GenericRoom.m

#import "GenericRoom.h"
@implementation GenericRoom
@synthesize mySprite, myType, test;

-(id)init {
    if (self = [super init]) {

    }
    return self;
}

-(id)initWithType: (enum Rooms) roomType {
    if (self = [super init]) {
        myType = roomType;

    }
    return self;
}

-(id)initWithSprite: (NSString *)file {

    if (self = [super init]) {
        mySprite = [CCSprite spriteWithFile:file];

        [self addChild: mySprite];
    }

    return self;
}
@end

RoomManager.h

#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "GenericRoom.h"
#import "RoomTavern.h"
#import "RoomEmpty.h"

enum Sides {
    LEFT, RIGHT, UP, DOWN
}theSides;

@interface RoomManager : CCLayer {
    CGSize size;
    NSMutableArray *myRooms;
}

- (void) CreateRoom: (enum Rooms)roomType;


@end

RoomManager.m

@implementation RoomManager

-(id)init {

    if (self = [super init]) {
        size = [[CCDirector sharedDirector] winSize];
        myRooms = [[NSMutableArray alloc] initWithCapacity:15];

        for (int i = 0; i < 15; i++) {
            GenericRoom *tmpRoom = [[GenericRoom alloc] initWithType:TAVERN];
            tmpRoom.test = 10;
            [myRooms insertObject:tmpRoom atIndex:i];
        }

        [self CreateRoom:TAVERN];
    }

    return self;
}

- (void) CreateRoom: (enum Rooms)roomType {
    switch (roomType) {
        case TAVERN:
        {
            //Create the Tavern Main Room
            RoomTavern *tmpRoom = [[RoomTavern alloc] initWithSprite:@"room-hd.png"];
            tmpRoom.mySprite.position = ccp(size.width/2,size.height/2);

            [self addChild:tmpRoom];

            [myRooms removeObjectAtIndex:8];
            [myRooms insertObject:tmpRoom atIndex:8];

            if ([self CheckAdjacentRooms:8 andSide:LEFT]) {
                RoomEmpty *tmpEmptyRoom = [[RoomEmpty alloc] initWithSprite:@"roomToBuild-hd.png"];
                tmpEmptyRoom.mySprite.position = ccp(tmpRoom.mySprite.position.x - tmpRoom.mySprite.contentSize.width, tmpRoom.mySprite.position.y);

                [self addChild:tmpEmptyRoom];

                [myRooms insertObject:tmpEmptyRoom atIndex:7];
            }

            break;
        }

        default:
            break;
    }
}

- (BOOL) CheckAdjacentRooms: (int)currentIndex andSide:(enum Sides)side {
    int leftRightSide = 0;
    if(side == LEFT)
        leftRightSide = -1;
    else if (side == RIGHT) 
        leftRightSide = 1;

    GenericRoom *roomTmp  = (GenericRoom *)[myRooms objectAtIndex:currentIndex + side];

    if (roomTmp.myType == EMPTY) {
        return YES;
    }
    else
        return NO;
}

@end

3 个答案:

答案 0 :(得分:0)

如果上面的代码是它在实际项目中的显示方式,那么问题是您要重新声明myRooms对象。当你写这一行时:

NSMutableArray *myRooms = [[NSMutableArray alloc] initWithCapacity:15];

您正在创建一个名为myRooms的新本地范围对象,当您退出当前范围(方法,块等)时会丢失该对象

解决此问题需要做的只是删除行开头的NSMutableArray *,然后将新分配的数组分配给您的属性。像这样:

myRooms = [[NSMutableArray alloc] initWithCapacity:15];

答案 1 :(得分:0)

提升@Dan F答案。读这个...

http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocObjectsClasses.html#//apple_ref/doc/uid/TP30001163-CH11-SW7

...什么是nil消息。您在本地声明的myRooms变量隐藏了您的myRooms属性(=实例变量)。换句话说,myRoomsnil。会发生什么......

GenericRoom *room = (GenericRoom*)[myRooms objectAtIndex: currentIndex + side];

由于nil消息传递规则,[myRooms objectAtIndex:...]会返回nil,因此您的room设置为nil

if (room.myType == EMPTY) {
    return YES;
}

room.myTypemyType对象发送消息room。因为roomnil,返回值是0 - 枚举确实包含整数标量值 - 这就是它返回0的原因。我假设EMPTY是你的枚举中的第一个元素=有值0。并0 == 0 =&gt;即使您的YES实例变量为myRooms,也会返回nil

答案 2 :(得分:0)

您的初始化程序似乎存在一些缺陷,可能会导致您的问题。

// NOTE: `Rooms` instead of `enum Rooms`
- (id)initWithType:(Rooms)roomType 
{ 
   if (self = [super init])  
   {
      // NOTE: accessor is used, otherwise the value is cleared when out of scope
      self.myType = roomType; 
   }
   return self;
}