Im writting a Simple SpriteKit game , but I have got a really serious error.
I created a Subclass of SKEmitterNode which i Named GameNode. I need it for some special instance methods. I set a property for this Custom Class(GameNode). Its the following:
#property (nonatomic,assign) nodetype GNodeType;
Yes, i ussing an enum for this property type. My enum is the following:
typedef enum {
nodetypeblue,
nodetypered,
nodetypegreen,
nodetypewhite
}nodetype;
Ok , now what is my problem. When I instance this class with the following custom init method:
-(id)initWithRandomTypeforSkScene:(SKScene*)Scene{
self=[super init];
if (self) {
nodetype type = arc4random_uniform(4);
self.GNodeType=type;
NSString *bluepath = [[NSBundle mainBundle] pathForResource:#"bluenode" ofType:#"sks"];
NSString *pathtoadd = [NSString string];
switch (type) {
case nodetypeblue:
pathtoadd = bluepath;
break;
//I have some possiblilies here i not list them all, its desnt matter
default:
pathtoadd = bluepath;
break;
}
self = [NSKeyedUnarchiver unarchiveObjectWithFile:pathtoadd];
self.position = CGPointMake(arc4random_uniform(Scene.size.width-40)+20, arc4random_uniform(Scene.size.height-40)+20);
//self.name = #"node";
[self setScale:0.25f];
return self;
}
else{
return nil;
}
}
OK, after that, I try to create az instance of this class like this:
GameNode * Node = [[GameNode alloc] initWithRandomTypeforSkScene:self];
//Self is a SKScene here
And here is my problem. This is returning a SKEmitterNode not a GameNode. How I know this? Because whenever i call for the Node.GNodeType the xcode send an Exception with the following error message:
-[SKEmitterNode GNodeType]: unrecognized selector sent to instance 0x10a022f80
Im setted lot of brakepoints and tried that i can, but it didnt solved anything.
Oh and after I create this instance called "Node" I checked, that right after creation the tpye is a SKEmitterNode not GameNode. If i check the type or the GnodeType inside my class everything is OK. I have problems just outside after the creating,initialization.Help please.
With help of LearnCocos2D i succesfully solved the issue.
SO I created a Property for my class which holds an SKEmitterNode. I added the sks to the property and i presented this Property instead of the whole class.
Related
I have created an NSArray from a text file with
void arrayfromfile {
// get a reference to our file
NSString *myPath = [[NSBundle mainBundle]pathForResource:#"CalendarQuotes" ofType:#"txt"];
// read the contents into a string
NSString *myFile = [[NSString alloc]initWithContentsOfFile:myPath encoding:NSUTF8StringEncoding error:nil];
// split our string into an array
NSArray *mySplit = [myFile componentsSeparatedByString:#"\n"];}
Now what I'd like to do is set label.text to mySplit[x] while x< mysplit.count and call it every time a user swipes up.
setlabeltextmethod quote {
if x<mySplit.count {
label.text = mySplit objectatindex x
x+=1
else { label.text = #"thats it folks" }
}
What I'm having trouble with is accessing mySplit from the quote so I can manipulate it to give me the quote at index x.
When I tried to access it from my swipe method:
- (IBAction)swipeUp:(id)sender {
[self doAnimationUp];
NSLog (#"swipedUp");
NSLog(#"array%#" , [mySplit objectAtIndex:0]);
NSLog(#"arraycreated");
//I'm using NSLog for debug purposes but this is where I would setlabeltext.text to mySplit objectAtIndex
}
I get array[null].
Your mySplit variable is local to arrayfromfile, so once that method returns the variable has gone. There is more than one approach to solving this. One is making it an instance variable, that is a variable that belongs to your current class instance and is visible to every instance method. Start you implementation like this:
#implementation MyClassName
{
NSArray *mySplit;
}
Now set the variable in the instance method arrayfromfile and read it in the instance method swipeUp - both calls must be made in the same instance of your class, each instance has its own set of instance variables.
Other options include adding a property to the class or, if you must, a global variable of some kind.
HTH
u1Option is an Option (custom class) object which is
declared and called in my ViewController viewDidLoad as:
- (void)viewDidLoad {
[super viewDidLoad];
Option *u1Option = [[Option alloc]init];
[u1Option setName: #"test"];
NSLog(#"Test1 Result: %#", u1Option.name);
}
Option is a custom class inheriting from NSObject and has a property declared in Option.h:
#property NSString *name;
However, if try to use u1Option in a IBAction, nothing is passed and while I get the "test" string in the Test1 NSLOG, on the contrary I get NULL in the Test2 NSLOG.
- (IBAction)addFirstOption:(UIButton *)sender {
NSLog(#"Test2 Result: %#", u1Option.name);
}
The Option instance is destroyed as soon as viewDidLoad returns. You need to put it in a property or instance variable. If it's already a property or instance variable then you are re-defining it, so use:
u1Option = [[Option alloc] init];
And this issue can be avoided in future by using self.u1Option or _u1Option.
I load a custom object using :
NSArray* array = [[NSBundle mainBundle] loadNibNamed:#"MyViewItem" owner:nil options:nil];
MyViewItem* myBaseItem = [array objectAtIndex:0];
In order not to perform the loadNibNamed action like a hundred times in the several loops I have to do, I plan to use this object as a "base" object that i'll fill with differents informations, but always based on the same design (like in an UICollectionView actually).
My first move was to set in my loop something like :
for (int i = 0; i < x; i++ ) {
MyViewItem* newItem = [myBaseItem copy];
}
Unfortunately, MyViewItem class tried to accessed "copyWithZone", which i didn't implement. On this point, i tried to inherits NSObject on it (I think all NSObject implements "copy" method), but the issue remains with the same error.
So I tried to inherits NSCopying, and to implement my copyWithZone method, which is the following (not working though) :
#interface MyViewItem : UIView <NSCopying>
// some stuff
#end
#implementation MyViewItem
// some stuff
- (id)copyWithZone:(NSZone *)zone
{
MyViewItem* copy = [[MyViewItem allocWithZone:zone] init];
// What should i do here ?
return copy;
}
#end
What am I missing ? I've read many issues concerning copy, but I couldn't solve mine :(
Thanks !
Here's my class with my custom init method:
// Piece.h
#import <Foundation/Foundation.h>
#interface Piece : CCSprite
#property (nonatomic) int pieceNumber;
+(Piece *)initWithPieceImage:(UIImage*)piece pieceName:(int)pName;
#end
// Piece.m
#import "Piece.h"
#implementation Piece
#synthesize pieceNumber = _pieceNumber;
+(id)initWithPieceImage:(UIImage *)piece pieceName:(int)pName
{
return [[[self alloc] initWithPieceImage:piece pieceName:pName] autorelease];
}
-(Piece*)initWithPieceImage:(UIImage *)piece pieceName:(int)pName
{
CCSprite *bgImage = nil;
if ( (self=[super init]) )
{
bgImage = [CCSprite spriteWithCGImage:piece.CGImage
key: [NSString stringWithFormat:#"%i",pName]];
}
return (Piece*)bgImage;
}
#end
I instantiated the Piece class like this to add it to the layer:
Piece *newPiece = [Piece initWithPieceImage:myUIImage pieceName:1];
[newPiece setPieceNumber:2]; //Error in this line
[self addChild: newPiece z:1];
However I have tried it like this and it perfectly works:
Piece *newPiece = [[Piece alloc] init];
[newPiece setPieceNumber:2];
but this is not what I want.
and here is the error I get:
[CCSprite setPieceNumber:]: unrecognized selector sent to instance 0x85f1050
Terminating app due to uncaught exception NSInvalidArgumentException, reason: -[CCSprite setPieceNumber:]: unrecognized selector sent to instance 0x85f1050
Aparently it looks like the problem is how Im trying to init my object.
I'm a newcomer to objective-c so I cant figure out what is wrong here.
any idea of what am I doing wrong here?
How can I achieve this approach and access the properties of my instantiated object with custom init method?
You have a mess in your code. In -(Piece*)initWithPieceImage:(UIImage *)piece pieceName:(int)pName you return a CCSprite object instead of a Piece. You assign self with an object but return another, of an incorrect type.
init returns the correct type (because you haven't reimplemented it), so it works, but you haven't actually initialized the image correctly.
You need to change your method like so:
-(Piece*)initWithPieceImage:(UIImage *)piece pieceName:(int)pName
{
return [super initWithCGImage:piece.CGImage key:[NSString stringWithFormat:#"%i",pName]];
}
It is because in your init method, you are for some reason creating a CCSprite object and returning that instead of the Piece object. Because of that, it will not be an object of your Piece class and will not respond to any of Piece's methods.
Instead of creating a new CCSprite object to set those properties to, you want to set those on self or super.
This problem has been confusing me for days now. I have an NSString, 'spriteType'. It is declared using the property and synthesise method. In my layer, where the string is created, I also create a CCNode. The node is created in a method.
- (void) spritePick {
CCMenuItemImage *go = [CCMenuItemImage itemFromNormalImage:#"button_go.png" selectedImage:#"button_go_selected.png" target:self selector:#selector(test)];
spritePickMenu = [CCMenu menuWithItems:go, nil];
spritePickMenu.position = ccp(0,0);
spritePick = [CCNode node];
[spritePick addChild:spritePickMenu];
spritePick.position = ccp(240,160);
[self addChild: spritePick];
}
The 'test' method, which is called from the button, is simple:
- (void) test {
NSLog(#"%#",spriteType);
}
The NSLog line crashes my game, and gives the error: EXC_BAD_ACCESS
Anywhere apart from inside the 'test' method, the code works fine. Why would it be giving me the error when the method has been called from the Node, but it would not give it to me when it has been called from anywhere else?
I can give you the full code if required.
Which attributes are you using for your spriteType property declaration?
If your project is using ARC, the header should look like:
#property (nonatomic, strong) NSString *spriteType;
While the implementation should look like:
#synthesize spriteType = spriteType_;
If you declare/synthesize your property this way, then NSLog(#"%#", self.spriteType) just writes (null) to the console (I tested to double-check).
It's a good practice to access your properties using self. rather than trying to access the backing ivar directly.
Since you're seeing EXC_BAD_ACCESS I assume you aren't maintaining a strong reference to self.spriteType.
If your project is using ARC, you need to be sure you're compiling with LLVM 3.0 or greater, as detailed in this answer.