Ошибка в Obj-C «нераспознанный селектор отправлен на экземпляр» - PullRequest
0 голосов
/ 08 ноября 2011

Некоторая информация: У меня есть два разных класса, "Дом" и "Казначейство". Они оба находятся внутри одного NSMutableArray, называемого «структурами». Дом имеет (int) переменную, называемую «собственность». Я использую для цикла (100 петель), чтобы создать дома и сокровищницы по всей области. Затем у меня есть другой цикл, который проходит по «структурам» и присваивает ему целое число «владение». В этом цикле я использую for (Houses * h в структурах), но по какой-то причине цикл также проходит через "казначейство" в структурах. Казначейство не имеет никакой переменной владения, и поэтому я получаю эту ошибку, сообщающую, что setOwnership: не существует. Я также использую Cocos2D, но это не должно иметь значения.

Вот как выглядит код:

// Variable
NSMutableArray *structures;


-(void) InitializeStructures
{
    structures = [[NSMutableArray alloc]init];

    for(int i = 0; i < initialColonies; i++)
    {
        House *h = [[House alloc]initWithFile:@"House.png"];
        h.position = [self ReturnPositionOnMap]; // Returns a point in playing area

        Treasury *t = [[Treasury alloc]initWithFile:@"Treasury.png"];
        t.position = [self ReturnFarPointNearOrigin:h.position];

        [structures addObject:h];
        [self addChild:h z:1];

        [structures addObject:t];
        [self addChild:t z:1];
    }
}

-(void) AssignOwnerships
{
    for(House *h in structures)
    {
        // Simplified to only show where the error occurs.
        h.ownership = [self ReturnID]; // Error occurs here.
        // The error ONLY occurs when it is iterating through a Treasury.
    }
}

Состав:

#import "CCSprite.h"
#import "ImportedGoods.h"

@interface Structure : CCSprite
{
    int _integrity;
    int _ID;
    bool _occupied;
    int _occupiedTimeLeft;
    int _occupiedTimeMax;
    Faction _faction;
}
@property(nonatomic, assign) int integrity;
@property(nonatomic, assign) int ID;
@property(nonatomic, assign) bool occupied;
@property(nonatomic, assign) int occupiedTimeLeft;
@property(nonatomic, assign) int occupiedTimeMax;
@property(nonatomic, assign) Faction faction;
@end

#import "Structure.h"

@implementation Structure

@synthesize integrity = _integrity;
@synthesize ID = _ID;
@synthesize occupied = _occupied;
@synthesize occupiedTimeLeft = _occupiedTimeLeft;
@synthesize occupiedTimeMax = _occupiedTimeMax;
@synthesize faction = _faction;

@end

Дом:

#import "Structure.h"
#import "ImportedGoods.h"

@interface House : Structure
{
    int _ownership;
}
@property(nonatomic, assign) int ownership;
@end

#import "House.h"

@implementation House

@synthesize ownership = _ownership;

@end

казначейство:

#import "Structure.h"

@interface Treasury : Structure
{
    int _storedWood;
    int _storedWater;
    int _storedStone;
    int _storedFood;
}
@property(nonatomic, assign) int storedWood;
@property(nonatomic, assign) int storedWater;
@property(nonatomic, assign) int storedStone;
@property(nonatomic, assign) int storedFood;
@end

#import "Treasury.h"

@implementation Treasury

@synthesize storedFood = _storedFood;
@synthesize storedWood = _storedWood;
@synthesize storedStone = _storedStone;
@synthesize storedWater = _storedWater;

@end

Это ошибка:

2011-11-07 18:45:29.016 Virtual World[788:10a03] -[Treasury setOwnership:]: unrecognized selector sent to instance 0x7498cc0
2011-11-07 18:45:29.022 Virtual World[788:10a03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Treasury setOwnership:]: unrecognized selector sent to instance 0x7498cc0'
*** First throw call stack:
(0x17fb052 0x198cd0a 0x17fcced 0x1761f00 0x1761ce2 0xcbe33 0xc2193 0xc1e5f 0xc1a34 0x3fc81 0xc185e 0x176151d 0x1761437 0x39b25 0x36ee2 0x17fcec9 0x91f91 0x92adf 0x94991 0x869a30 0x869c56 0x850384 0x843aa9 0x27affa9 0x17cf1c5 0x1734022 0x173290a 0x1731db4 0x1731ccb 0x27ae879 0x27ae93e 0x841a9b 0xc07ef 0x20c5 0x1)
terminate called throwing an exception(gdb) 

Я знаю, что могу просто создать другой NSMutableArray, называемый "treasuries", но я бы хотел сохранить все в одном массиве, если это возможно. Я хочу знать, почему он все еще перебирает казначейские обязательства, хотя я и определил перебирать «Дом * h в структурах». Если вам нужна дополнительная информация, прокомментируйте ниже, и я добавлю. Спасибо!

Ответы [ 2 ]

4 голосов
/ 08 ноября 2011

Когда вы используете быстрое перечисление в Objective-C, что является синтаксисом:

for (MyClass *item in someArray) {
    ...
}

То, что вы делаете, - это циклический перебор каждого элемента в массиве, обработка каждого элемента как указателя на MyClass объект, независимо от того, что это за элемент на самом деле или нет . Он не делает то, что, как вы думаете, делает, то есть выполняет итерацию только по элементам в массиве того типа, который вы объявляете в цикле.

Что вы, вероятно, должны сделать, это хранить ваши элементы House и Treasury в отдельных массивах. У вас есть конкретная причина для того, чтобы поместить их в одну структуру?

Если вы действительно хотите хранить их вместе, вы можете использовать:

for (id item in structures) {
    if ([item isKindOfClass:[House class]]) {
        House *house = (House *) item;
        [house setOwnership:...];
    } else {
        continue;
    }
}
3 голосов
/ 08 ноября 2011

Ваше предположение, что

for(House *h in structures)
    {
        // Simplified to only show where the error occurs.
        h.ownership = [self ReturnID]; // Error occurs here.
        // The error ONLY occurs when it is iterating through a Treasury.
    }

выберет только объекты Дома из массива неправильно. Вы получите каждый объект из массива. House *h in structures сообщает компилятору, что массив заполнен объектами House.

Вы должны изменить его на

for (id h in structures){
// Simplified to only show where the error occurs.
     if ([h respondsToSelector:@selector(setOwnership:)]){
          h.ownership = [self ReturnID];
     }
}
...