0
votes

I'm getting the following error trying to add enemy nodes to my scene. The error message is : Attemped to add nil node to parent: <SKNode> name:'(null)' position:{0, 0} accumulatedFrame:{{inf, inf}, {inf, inf}}

(
    0   CoreFoundation                      0x00007fff905a541c __exceptionPreprocess + 172
    1   libobjc.A.dylib                     0x00007fff8a101e75 objc_exception_throw + 43
    2   CoreFoundation                      0x00007fff905a52cc +[NSException raise:format:] + 204
    3   SpriteKit                           0x00000001000cc754 -[SKNode addChild:] + 161
    4   InvadersMacTest                     0x0000000100011fe0 -[MapScene initWithSize:] + 3552
    5   InvadersMacTest                     0x00000001000042fb -[OpcionesMenu handleKeyEvent:keyDown:] + 875
    6   InvadersMacTest                     0x0000000100004514 -[OpcionesMenu keyUp:] + 100
    7   SpriteKit                           0x000000010008ded8 -[SKView keyUp:] + 67
    8   AppKit                              0x00007fff8ee90f71 -[NSWindow sendEvent:] + 3721
    9   AppKit                              0x00007fff8ee31ca2 -[NSApplication sendEvent:] + 3395
    10  AppKit                              0x00007fff8ec81a29 -[NSApplication run] + 646
    11  AppKit                              0x00007fff8ec6c803 NSApplicationMain + 940
    12  InvadersMacTest                     0x0000000100003902 main + 34
    13  libdyld.dylib                       0x00007fff8d75a5fd start + 1

The code used to add the node is the following, i'm not doing something exceptional or tricky, just create a rectangle which simulate an enemy.

SKScene method

self.almacenEnemigos = [[NSMutableArray alloc] initWithCapacity:kNumEnemigos];

for(int i = 0; i < kNumEnemigos; i++)
{
     enemigo *nemesis = [[enemigo alloc] init];
     [nemesis pintarEnemigo:CGPointMake(200+5*i, 200+5*i)];
     [self.almacenEnemigos addObject:nemesis];
     [self.world addChild:nemesis->cobra];
}

And the method pintarEnemigo in enemigo class:

@interface enemigo()
    @property (nonatomic) SKSpriteNode *cobra;
@end

-(SKSpriteNode*)pintarEnemigo:(CGPoint) pos
{
    self.cobra = [[SKSpriteNode alloc] initWithColor:[SKColor orangeColor]
                                                        size:CGSizeMake(80.0f, 60.0f)];
    self.cobra.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:25];
    self.cobra.physicsBody.dynamic = YES;
    self.cobra.position = CGPointMake(pos.x, pos.y);
    self.cobra.name = @"Pulpo";

    return self->cobra;
}

and enemigo.f file as demanded:

@interface enemigo : personaje
{
    @public
        SKSpriteNode *cobra;
}

-(id)init;
-(SKSpriteNode*)pintarEnemigo:(CGPoint) pos;

-(BOOL)enviarMensaje;
-(BOOL)mensajeRecibido;
2
Can you show us enigmo.h? I think you made a mistake there too. - Abhi Beckert
header file enemigo added - Jorge Vega Sánchez
Updated my answer, now that I've seen enigmo.h - Abhi Beckert

2 Answers

1
votes

What is self->cobra? That's your bug. The value is nil. It's never set to the object you created a few lines earlier.

I'm pretty sure you meant to use self.cobra.

The -> operator exists in Objective-C but should pretty much never be used, except maybe once or twice in ten years of programming. You should definitely never use it on self, although it is syntactically correct.

Your class has two instance variables, one is cobra and the other is _cobra. You're setting a value to _cobra and then returning the value of cobra.

self.cobra will return access _cobra, while self->cobra will access cobra.

In your *.h file, this line is incorrect:

 SKSpriteNode *cobra;

You have three options to fix it:

  • change it to be named _cobra, which is the correct name for @property cobra;
  • delete the line altogether, and then the compiler will created _cobra automatically for you.
  • add an @synthesize rule to the enigmo.m file telling the compiler to use cobra instead of _cobra (lookup the documentation for @synthesize to learn how).

Once you've done that, you need to change the return self->cobra line to either:

  • return self.cobra;
  • return _cobra;
  • return cobra;

Which one depends on what you do in the header file, but I suggest the first option, since that is the generally accepted best practice for obj-c programming.

0
votes

What happens if you change:

@interface enemigo()
    @property (nonatomic) SKSpriteNode *cobra;
@end

to

@interface enemigo()
    @property (nonatomic,strong) SKSpriteNode *cobra;
@end