Calling a instance method while using childNodeWithName - ios

Is it possible to call an instance method without using an instance variable or #property?
Here is how I create an instance of a class. Within the method, I try to call on the class's instance movement method to force the instance to move:
-(void)createCharacterNPC
{
int randomness = [self getRandomNumberBetweenMin:1 andMax:20];
for (int i = 0; i < randomness; i += 1)
{
NSString *npcName = [NSString stringWithFormat:#"anNPC%i", randomness];
NPCclass *NPC = [[NPCclass alloc] initWithName:npcName];
NPC.position = CGPointMake(self.size.width/2, self.size.height/2);
NPC.zPosition = 1.0;
[_worldNode addChild:NPC];
// THIS OBVIOUSLY WORKS. But I can't use this technique outside this method.
[NPC beginMovement];
// THIS IS WHAT I WANT, BUT XCODE DOESN'T ALLOW ME TO WRITE CODE THIS WAY.
[[_worldNode childNodeWithName:#"anNPC1"] beginMovement];
}
}
Is there a way to allow [[_worldNode childNodeWithName:#"anNPC1"] beginMovement]; to work? Or some way similar to this so I wouldn't have to have create an instance variable of NPC (like so: _NPC)?
I'm asking because all of this is happening inside a mini-game scene and NPCclass will be initialized a random number amount of times (with arc4random() method). NPCclass moves on its own using vector (physics in a platformer) movement but I need to initialize its movement method right after creation then I need to periodically access each individually created instance of NPCclass using its name in other methods of the scene. Since I don't know how many NPCclass instances will be created each time the mini-game is played, I CAN'T use IVAR's or something like #property NPCclass *anNPC;
Please help.

Xcode complains about
[[_worldNode childNodeWithName:#"anNPC1"] beginMovement];
because the method -childNodeWithName returns an SKNode object. Instances of the SKNode class do not respond to the selector -beginMovement (or as Xcode puts it, no visible #interface declares the selector -beginMovement). Xcode shows this to you to force you to make sure you wrote what you wanted to write. Since you are sure, you can tell Xcode that the returned object is of the type NPCclass.
(NPCclass *)[_worldNode childNodeWithName:#"anNPC1"]
Now you can expand the statement to call -beginMovement.
[(NPCclass *)[_worldNode childNodeWithName:#"anNPC1"] beginMovement];
Note
There are a few concepts which you might be confusing. NPCclass is a class. +node is a class method of SKNode, which you can call with [NPCclass node];. -beginMovement is an instance method, called with:
NPCclass *npc = [NPCclass node];
[npc beginMovement];
Or:
[(NPCclass *)anyObject beginMovement];
// make sure anyObject responds to this selector though, or you app will crash.
Class methods are prefixed with a +, instance methods with -.

Class methods do not use an instance, just the class name.
As an example consider the
NSString` class method: `+ (id nullable)stringWithContentsOfFile:(NSString * nonnull)path
and a usage:
NSString *fileData = [NSString stringWithContentsOfFile:filePath];

Related

Objective-C and the self keyword [duplicate]

What does self mean in Objective-C? When and where should I use it?
Is it similar to this in Java?
self refers to the instance of the current class that you are working in, and yes, it is analagous to this in Java.
You use it if you want to perform an operation on the current instance of that class. For example, if you are writing an instance method on a class, and you want to call a method on that same instance to do something or retrieve some data, you would use self:
int value = [self returnSomeInteger];
This is also often used for accessor methods on an instance (i.e. setters and getters) especially with setter methods, if they implement extra functionality rather than just setting the value of an instance variable, so that you do not have to repeat that code over and over when you want to set the value of that variable, for example:
[self setSomeVariable:newValue];
One of the most common uses of self is during initialization of a class. Sample code might look like:
- (id)init
{
self = [super init];
if(self!=nil) {
//Do stuff, such as initializing instance variables
}
return self;
}
This invokes the superclass's (via super) initializer, which is how chained initialization occurs up the class hierarchy. The returned value is then set to self, however, because the superclass's initializer could return a different object than the superclass.
self is an implied argument to all Obj-C methods that contains a pointer to the current object in instance methods, and a pointer to the current class in class methods.
Another implied argument is _cmd, which is the selector that was sent to the method.
Please be aware that you only get self and _cmd in Obj-C methods. If you declare a C(++) method, for instance as a callback from some C library, you won't get self or cmd.
For more information, see the Using Hidden Arguments section of the Objective-C Runtime Programming guide.
Yes, it's exactly the same as "this" in Java - it points to the "current" object.
Two important notes:
The class itself, e.g. UIView (I'm NOT talking about a UIView object) is itself an object, and there is a self associated with it. So for example, you can reference self in a class method like this:
// This works
+(void) showYourself { [self performSelector: #selector(makeTheMostOfYourself)]; }
// Class method!
+(void) makeTheMostOfYourself { }
Note that the compiler does NOT raise any warnings or errors, even if the self you mean to reference is an object and not a class. It is VERY easy to cause crashes this way, for example:
// This will crash!
+(void) showYourself { [self performSelector: #selector(makeTheMostOfYourself)]; }
// Object method!
-(void) makeTheMostOfYourself { }
// This will crash too!
-(void) showYourself2 { [self performSelector: #selector(makeTheMostOfYourself2)]; }
// Class method!
+(void) makeTheMostOfYourself2 { }
Sadly, this makes class methods a bit harder to use, which is unfortunate because they are a valuable tool for encapsulation through information hiding. Just be careful.
Wow, that many half-correct answers and misleading hints. This let me answer the Q even there is a accepted answer for years:
First of all: It is really hard to compare a concept of messaging/calling in the context of an early binding, static typing language as Java with a late binding, dynamically typing languages as Objective-C. At one point this will break. I would say: No, this is not similiar, since the typing and dispatching concepts of both language are fundamental different so nothing can be similar to the other one. However, …
Then we should differ between the "two sides" of self.
A. Using self
When you use it in a message, it is simply an object reference as any other:
[self doSomething];
[anotherObject doSomething];
Technically both lines works identically (accept of having a different receiver, of course). This especially means, that the first line does not lead to an execution of a method inside the class of self, because self does not necessarily refer to "that class". As every message inside Objective-C (single exception: messages to super)this can lead to the execution of a method in a subclass:
#interface A : NSObject
- (void)doSomething;
- (void)doAnotherThing;
#end
#implementation
- (void)doSomething
{
[self doAntoherThing];
}
- (void)doAnotherThing
{
NSLog( #"A" );
}
#interface B : A
- (void)doSomething; // Not necessary, simply as a marker
#end
#implementation B
- (void)doAnotherThing
{
NSLog( #"B" );
}
In a code like this
B *b = [B new;]
[b doSomething];
The line
[self doAnotherThing];
in class A will lead to the execution of -doAnotherThing (B), because messages to self are late bound as every other message. The result on the console will b "B", not "A". Using self as a receiver you should not think of a single special rule. There is completely none.
(And the above example is a very good example for using self in class methods, because the same situation can occur on class methods. Using the class itself breaks polymorphism, what is one of the worst idea at all in OOP. DO use self in class methods, too.)
B. Getting self
What is self pointing to? It points to the object to whom the message is sent that caused the execution of the current method.
Having …
…[someObject doSomething]… // some object is a reference to an instance object
… as a message, a method is called, in the most simple case …
- (void)doSomething
{ … }
In such a case, self can point to an instance of the class, the method belongs to. And it can point to an instance of a subclass, the method belongs to, too. You don't know. (And this information is preserved using self to send a message as explained above.)
If the message is sent to a class object, self points to the class object, that was the receiver of the message. This is completely analogous. Therefore it is possible that self points to a subclass object:
#interface A : NSObject
+ (void)doSomething;
+ (void)doAnotherThing;
#end
#implementation
+ (void)doSomething
{
[self doAntoherThing];
}
+ (void)doAnotherThing
{
NSLog( #"A" );
}
#interface B : A
- (void)doSomething; // Not necessary, simply as a marker
#end
#implementation B
+ (void)doAnotherThing
{
NSLog( #"B" );
}
Having this classes
…[A doSomething]…
self inside -doSomething (A) points to the class object of B. Therefore [self doAnotherThing] of B(!) is executed. This is clearly different from
+ (void)doSomething
{
[A doAntoherThing];
}
The latter version causes relevant harm to the principles of OOP.
As a side note it is possible that self inside a class method of a root class points to an instance object of the root class or any subclass. You have to keep this in mind, when writing categories on NSObject.
self is an object pointer to the current instances dispatch table. It is an implicit first argument to every member function of an object, and is assigned when that function is called.
In functions like init, you need to be careful that when you call the super class init you reassign self to be the return value as the super class init may redefine what self points to.
super is similar to self except it points to the superclass dispatch table.

How would you get the update method to be called in a class other than MyScene in Objective-C's Sprite-Kit project?

So I'm in the process of making a Objective-C Sprite-Kit based game. I'm fairly new to Objective-C so I seem to be stuck on something involving the update method.
Traditionally in the default Sprite-Kit project it generates for you create a View which contains a scene which contains all the nodes that you want to manipulate. It also comes with a pre-generated, empty update method which since then I have replaced with my own (which works great). But I do not want my update method to based in the MyScene class and this is where my problem lies. If I leave the update method in the MyScene class I can see using NSLog that is in fact continuously being called like it should be, but if I move it say to the ViewControler class it won't be called at all.
My question is how would I go about getting it to call the update method in a class other than MyScene..? You may be asking why I would want to do this so I'll explain below but its not fully necessary to answer the question, however if you do have any tips on my program please let me know!
Traditional Sprite-Kit Project
ViewController --> Creates a MyScene (which is just inheriting from SKScene)
MyScene --> Creates all the nodes, and has the update method to hand game logic/graphics.
My Ideal Structure for my Sprite Game
ViewController --> Creates a ForegroundScene and BackgroundScene(still inherits from SKScene)
ForegroundScene --> creates all the nodes/characters for the game
BackgroundScene --> Creates the Sky, clouds, general landscape stuff for the game.
GameController --> contains the update method which calls displayView and updateGame.
Edit: To clear up any confusion, ForgegroundScene and BackgroundScene are essentialy the same thing as the MyScene class which was originally generated, but now there are two classes re-named, one containing stuff for the background, the other for the foreground.
Update Game is still located in the GameController class and it just does things like collision test, updates position of nodes, deletes characters that were killed.
DisplayView is located in the ViewController and its name is self-explanatory it displays the view of the game which is composed of nodes from the BackgroundScene and the ForegroundScene.
Anyway, this is my idea set up for a game, not sure how pratical it is. I'm very open to suggestions.
Here is my intended update method incase you are interested in seeing it but like I said I test it with NSLog and it ticks accordingly but in any other class its never called.
-(void)update:(CFTimeInterval)currentTime
{
const int TICKS_PER_SECOND = 35;
const int SKIP_TICKS = 1000 / TICKS_PER_SECOND; //these ivars would be moved to top of intended class
const int MAX_FRAMESKIP = 10;
NSDate *referenceDate = [NSDate date];
double timePassed_ms = [referenceDate timeIntervalSinceNow] * -1000.0;
NSUInteger next_game_tick = timePassed_ms;
int loops;
bool game_is_running = true;
while( game_is_running ) {
loops = 0;
while([referenceDate timeIntervalSinceNow] * -1000.0 > next_game_tick && loops < MAX_FRAMESKIP) {
[self updateGame] //calls GameController to do logic updates/collision test, etc.
NSLog(#"update game");
next_game_tick += SKIP_TICKS;
loops++;
}
[self displayGame]; //calls viewcontroler to display game
}
}
You could make the class that you want to notify every time you call -update: an instance variable of your scene, then just forward the message to that class. For example, create an instance variable in your scene of the class you want to notify.
#interface MyScene ()
#property (nonatomic) ClassToNotify *notify;
#end
Then in your -update: method, just notify the instance variable.
- (void)update:(CFTimeInterval)currentTime
{
// pass the message on
[self.notify notifyThatUpdateWasJustCalledWithTime:currentTime];
}
In this case, -notifyThatUpdateWasJustCalledWithTime: would be a method of your ClassToNotify class.

Accessing an instance variable from another class for cocos2d project?

In my cocos2d game, I have a "powerup" of sorts where, once attained, the character becomes blue, the platform becomes blue, and so does the background. I'm not sure if I am implementing this in the best way so if you have other suggestions please do share!:)
I created a class Blue that has an instance variable called blueCalled
I imported this class to both my "Platform" class as well as my "Player" class.
The powerup and player colliding code is inside my Platform class. This is the code for when the powerup is hit:
// try remove powerup
- (void) tryRemovePowerup
{
NSMutableArray * currentPowerUpArray = [self getcurrentPowersArr];
if(currentPowerUpArray)
{
int playerY = ((CCLayer*)(self.player)).position.y;
for(int x=0; x<[currentPowerUpArray count];x++)
{
CCSprite *powerup = [currentPowerUpArray objectAtIndex:x];
if(abs(powerup.position.x+powerup.parent.position.x-[Player initX])<50)
{
if(abs(powerup.position.y+blueberry.parent.position.y-playerY)<30 && powerup.visible && powerup.visible)
{
[power.parent powerup cleanup:YES];
CGSize winSize = [[CCDirector sharedDirector] winSize];
[[SimpleAudioEngine sharedEngine] playEffect:#"yay.wav" pitch:1 pan:0 gain:1];
// THIS IS WHERE ALL OF EFFECTS SHOULD HAPPEN
NSLog(#"powerup hit");
}
}
}
}
[self hitTestOB];
}
The place of // THIS IS WHERE ALL OF EFFECTS SHOULD HAPPEN is where I want to make everything blue. Right now, I plan to do this by setting the instance variable in the Blue class to YES.
In the methods that take care of the 1. frames of the main player, 2. background, and 3. platform frames, I have an if statement checking if the instance variable of the Blue class is YES or NO and it acts accordingly.
However, I don't know how to use the instance variable from the Blue class in my platform and player class, also, I'm not 100% confident this is the best way to implement a powerup.
Thank you for any help you can provide me :)
Go iOS!
As a general rule, if you want to access an iVar of another object, you should make a property to access it. This is not an exception to that rule, but I'll tell you how to do it anyways.
Objective C objects are inherently C structures. This means that the -> operator works on them. In this case, you would want to use blue->blueCalled, where blue is the instance of your Blue class.
Visibility is the key to this working (or failing). You can only use this if the iVar is declared within the #interface in the header file and not following and #private or #protected declaration.

EXC_BREAKPOINT: Message sent to deallocated instance

I get the above message in XCode 4.6. I've done a pretty thorough search and but nothing seems to match the exact circumstances surrounding my issue. Admittedly, I'm relatively new to iOS dev, and memory-management has never been my strong suit, but this just has me completely miffed.
I have an instance variable theLink which is defined in the class Game as follows:
#interface Game : NSObject
// Class objects
#property(nonatomic,retain) NSMutableArray *queryItems;
#property(nonatomic,retain) NSMutableArray *theArray;
#property(nonatomic,retain) NSString *theLink;
#property(nonatomic,retain) NSString *thePath;
theLink is set in the makeGame method which is called in the method initialiseGame in my view controller:
- (void) initialiseGame
{
bool gameCreated = FALSE;
while (!gameCreated)
{
gameCreated = [theGame makeGame:#"ptl"];
}
[loadingIndicator stopAnimating];
[loading setText:#"Tap to Start"];
[self performSelector:#selector(setLabels) withObject:nil afterDelay:0.0];
}
(Note: the performSelector afterDelay is used to allow the view to update before continuing. Bit of a hack but I couldn't work out a better way!)
The app then loads the game, and when the user taps the screen to start, the next method which is called from the view controller is:
- (void) setupLink
{
...
for(int i=0; i<[theGame.theLink length]; i++) {
...
}
}
It is on this reference to theGame.theLink where I'm am getting the crash.
What has me most confused is that if I call theGame.theLink from inside the initialiseGame method, it is displays correctly, and also calling any other variable from the Game class (such as thePath or theArray works perfectly, so theGame object has not been deallocated in it's entirety, only the variable theLink.
It seems to me that the variable is being deallocated somewhere as the view controller is being updated. I haven't released the variable, and can't work out why only this variable is being deallocated. As I said at the start, memory-management is not my strength!
Any help/ideas would be hugely appreciated. Let me know if you require any more details.
Thanks heaps,
Andrew
EDIT: Setting of theLink within makeGame
- (bool) makeGame:(NSString*)gameType
{
...
[self getLink];
}
- (void) getLink
{
...
if (... && ((arc4random() % 10) > 8))
{
theLink = #"Animals";
}
}
There are many different ways theLink may be set, depending on random numbers and other factors. This is the most basic form which simply sets it to a static string. It doesn't matter how theLink is set or what it is set to, the program always crashes at the same point.
If theLink is being set to the parameter being passed to it ,#"ptl" or some similar temporary string, it will give you a problem, because it is just a pointer pointing at the current location that is holding #"ptl". After the makeGame method is completed, your system will assume that it is all done with #"ptl" and just free it up.
When you make an #"stringwhatever" in your code, it is supposed to be the equivalent of making an NSObject that is an immutable literal instance of #"stringwhataver". It should, in theory handle all the reference counting in a nice way, but when you are doing your own memory management, there are so many ways to lose count of your references.
There's a pretty simple rule to follow. If you've declared properties, access them via the property. To do otherwise (as you are doing above, with theLink = ...) bypasses all of the memory management built into the property accessors.
self.theLink = ...
Would have solved this problem under MRC. Switching to ARC has "solved" your problem without you understanding the root cause.

How do I access instance variables inside an instance method called from an instance method at the same level

I have an IBAction instance method that is connected to a slider, and displays the slider value in a Text Field that has the name datacellR1. A copy of the code is below, followed by a question. Both methods are in the #implementation section of the View2Controller.m file.
- (IBAction)slider1Change:(id)sender
{
float pctVal1 = [slider1 floatValue]; // this works
[datacellR1 setFloatValue:pctVal1];
[View2Controller CalculateUpdatedTotal ]; // This method needs to work with the datacellR1 contents, but I can’t access it.
}
-(void)CalculateUpdatedTotal
{
// -------- do some work with datacellR1 ----
// This function fails with an error
float newValue = [datacellR1 floatValue];
//some other code goes here
}
The error in slider1Change is that CalculateUpdatedTotal method is not found. If I change CalculateUpdatedTotal from an instance method to a class method, the error is that the Instance variable datacellR1 accessed in a class method.
Any suggestions on how I can make this work?
CalculateUpdatedTotal, as written, is also an instance method. Therefore, to invoke it, you should pass the message to self, not the class (View2Controller):
[self CalculateUpdatedTotal];
By the way, it's conventional to begin method names in Objective-C with a lower-case letter.

Resources