1

I have been trying to use some objective C, i have got as far as creating a couple of objects and im now trying to instantiate them. The code compiles with no warnings but when it runs i get this in the console:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason:
'-[CCSprite copyWithZone:]: unrecognized selector sent to instance 0x6424ad0'

Im guessing there is just a problem with the code somewhere, im not calling a copyWithZone method anywhere

Here is the code for game object:

gameobject.h

#import "cocos2d.h"
#import "Box2D.h"

@interface GameObject : NSObject {

    }

-(id) initWithSprite:(CCSprite*) sprite
         andVelocity:(b2Vec2*) velocity;

@property (nonatomic, copy) CCSprite *Sprite;
@property (nonatomic) b2Vec2 *Velocity;

@end

gameobject.mm

#import "cocos2d.h"
#import "GameObject.h"
#import "Box2D.h"

@implementation GameObject

@synthesize Sprite;
@synthesize Velocity;

-(id) initWithSprite:(CCSprite*) sprite
         andVelocity:(b2Vec2*) velocity
{
    self = [super init];

    self.Sprite = sprite;
    self.Velocity = velocity;

    return self;
}

@end

here is the code for BodyObject:

BodyObject.mm

#import "BodyObject.h"


@implementation BodyObject

@synthesize Body;
@synthesize Fixture;

-(id) initWithBody:(b2Body*) body 
        andFixture:(b2Fixture*) fixture 
       andVelocity:(b2Vec2*) velocity 
         andSprite:(CCSprite*) sprite
{
    self = [super initWithSprite:(CCSprite*)sprite 
                     andVelocity:(b2Vec2*)velocity];

    self.Body=body;
    self.Fixture=fixture;

    return self;
}

@end

BodyObject.h

#import "GameObject.h"
#import "Box2D.h"
#import "cocos2d.h"

@interface BodyObject : GameObject {

}

@property (nonatomic) b2Body *Body;
@property (nonatomic) b2Fixture *Fixture;

-(id) initWithBody:(b2Body*) body 
        andFixture:(b2Fixture*) fixture 
       andVelocity:(b2Vec2*) velocity
         andSprite:(CCSprite*) sprite;

@end

And where im trying to instantiate it

BodyObject *bodyObject = [[BodyObject alloc] initWithBody:(b2Body *)body 
                                               andFixture:(b2Fixture *)fixture 
                                              andVelocity:(b2Vec2*) vector 
                                                andSprite:(CCSprite*) sprite];

Can anyone point me as to where to start looking for the solution for these types of errors or see a problem with the code? I can post more of the classes if required.

Thanks,

2
  • 1
    As a side-note, take out all the unnecessary casts. eg. initWithSprite:sprite andVelocity:velocity. Casting is extremely dangerous as it masks warnings - ie you can get any old crap to compile with zero warnings if you put enough casts in. You will need to use casts sometimes but only use them when there is a real need. Also, property names should always begin with lower-case
    – hooleyhoop
    Commented Feb 20, 2011 at 19:34
  • Thanks, I have amended the code and example. I think i must have put that there when I was trying to make the method work, there were colons all over the place!
    – WraithNath
    Commented Feb 20, 2011 at 19:37

3 Answers 3

5

This is wrong: self = [[super initWithSprite:(CCSprite*)sprite andVelocity:(b2Vec2*)velocity] alloc];

The right procedure is: self = [super initWithSprite:(CCSprite*)sprite andVelocity:(b2Vec2*)velocity];

7
  • Hi, thanks, I have changed the code above to: #import "BodyObject.h" @implementation BodyObject @synthesize Body; @synthesize Fixture; -(id) initWithBody:(b2Body*) body andFixture:(b2Fixture*) fixture andVelocity:(b2Vec2*) velocity andSprite:(CCSprite*) sprite { self = [[super alloc] initWithSprite:(CCSprite*)sprite andVelocity:(b2Vec2*)velocity]; self.Body=body; self.Fixture=fixture; return self; } @end but now i get the message: GameObject may not respond to -alloc
    – WraithNath
    Commented Feb 20, 2011 at 19:11
  • 1
    My mistake. You shouldn't have [super alloc] at all.. Is is incorrect.
    – Tiago
    Commented Feb 20, 2011 at 19:14
  • Thanks it was the alloc method. i have updated the code to the latest version. trouble is im now getting a different error when running...*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CCSprite copyWithZone:]: unrecognized selector sent to instance 0x6424ad0'. (also updated above) i dont think im calling this copyWithZone method anywhere!?
    – WraithNath
    Commented Feb 20, 2011 at 19:32
  • 1
    The problem is you're declaring the Sprite property as copy but CCSprite doesn't implement copying. You probably don't want to declare the property that way. Commented Feb 20, 2011 at 19:38
  • 1
    The +(id)alloc method call is a Class method, not an instance one. Since it's the same for all instances of the class. Generally, you can think of it as the C malloc(size_t size) function, being the size given by the class.
    – Tiago
    Commented Feb 20, 2011 at 20:54
1

If you've reached the point in your code where your custom init methods are being called, then your object has already been allocated, so remove those outer calls to +alloc altogether.

(Also, unrelated, but the convention when naming selectors is not to include works like and, or, and but. Something like -initWithSprite:velocity: would conform to the Cocoa naming conventions.)

2
  • Thanks, it was the alloc method. I have just been trying to learn objective-c from a .net background so calling methods like that is very unusual to me at the moment!
    – WraithNath
    Commented Feb 20, 2011 at 19:34
  • No worries. :) It takes a while to transition.
    – CIFilter
    Commented Feb 20, 2011 at 19:51
1

The likely reason for this crash is the CCSprite does not conform to NSCopying. If you either implement NSCopying on CCSprite (providing a copyWithZone: method) or change your Sprite property to retain, this crash will stop.

As a side note, accepted Objective-C style frowns upon any variable starting with a capital letter.

6
  • Thanks, that sorted it! should I normally use retain for properties? I would mark as answer but Tiago was first to answer. +1 though :)
    – WraithNath
    Commented Feb 20, 2011 at 19:40
  • 1
    I'd say retain unless you definitely want to copy the object, or you are concerned that the object is mutable and another object may mutate it without your knowledge. There are a lot of considerations however. Commented Feb 20, 2011 at 19:42
  • 1
    properties invoke [obj autorelease] to the requested member which means that obj is added to an autorelease pool. Considering that this pool is drained at least once every thread loop, if you want to keep the object alive for more than that, you should retain it.
    – Tiago
    Commented Feb 20, 2011 at 20:58
  • @tiago could you elaborate on that? Commented Feb 20, 2011 at 22:00
  • 1
    For each thread in the Cocoa framework you have at least one NSAutoreleasePool. When you do obj.variable, if you defined the property with the retain option, variable is added to the autorelease pool. At the end of each run loop, that pool is drained (releasing every object that was added) and thus, if you have an object retained only by that pool, that object is deallocated.
    – Tiago
    Commented Feb 20, 2011 at 22:38

Not the answer you're looking for? Browse other questions tagged or ask your own question.