can I compile void like this?

I am using Objective C to compile the method. Can I compile like this?

-(void)someMethod{
    ...;
}

+(void)someMethod{
    [self someMethod]; //To implement the -(void) method above.
}

Because when my app implement this method, it crashes. How should I compile. Please help. Thanks.

Replies

I believe you will have to call the second of your two methods "someMethod" by a different name since [self someMethod] can be sent a +(void).


By the way, calling a "method" a "void" is unusual if not wrong. A method that returns nothing (i.e. returns void) is a "method".

Actually, the reason it doesn't work is more fundamental. Line 1 is an instance method, and line 5 is a class method. Inside a class method, "self" represents the class object (a metaobject), not an instance of the class. Therefore line 6 calls the class method, not the instance method. The fact that the two methods have the same name is not a problem (though it is, of course, confusing).


Also, a class method can't call an instance method without a reference to some instance. (Again, "self" isn't a reference to an instance of the class.) That rule is true even if the methods involved have no parameters, no return value and don't use any per-instance variables.


The answer to "How should I compile"? is: you can't.

> "self" represents the class object (a metaobject), not an instance of the class.

Are you sure? When called from a class method in a non-instantiated class, perhaps. But when called (by an instance method) within an instance aren't you messaging that same instance of the class?


>Therefore line 6 calls the class method, not the instance method.

Then the problme would be the infinte loop

Yes, I'm sure. The call in line 6 isn't within an instance method. It's within a class method.


It looks odd, but in that case "self" is an instance of class Class (actually a subclass of Class that represents the metaclass of the class that contains these declarations). Technically, line 6 can be regarded as an instance method invocation for an instance of <SomeSubclassOfMetaclassClass>, but it's easier to think of it as a class method invocation. 😉


So, yes, I imagine the crash would have been due to the stack filling up because of an infinite recursive call.

So can anyone please give me some sample code how to write. Because when I write like this Xcode give me an error "No known class name for selector..."

+(void)someMethod{
...   //Error here
}

Please help.

For more information, when I delete the code with error and declare it in header file. I get this error "instnce variable 'the thing I declare in .h file' accessed in class method".

What I meant is how to add instance variable like SKNode or SKSpriteNode into the class method. Please give sample code. Thanks

>> how to add instance variable … into the class method


You can't.


An instance variable needs an instance. A class method doesn't have an instance.

OK. So how can I call a method from another class. I use class mthod but I can't declare the SKNode in it. What can I do? Please help. Thanks

You want to call an instance method not a class method - "-(void)".

Note that a class method that returns nothing - what you are calling "void" - may not make a lot of sense because it returns nothing. Usually a class method is "+(NSstring *)" or "+(NSDictionary *)" so that it can return something. Usually it has arguements included in the call to the method so it has something to work with. I suspect you have gone down a rabbit hole with these class methods. I suspect that all along what you want to do is create an instance of a class and call instance methods that start with "-". Only use a "+" if you are certain you don't want an instance of the class.

>> I suspect you have gone down a rabbit hole with these class methods.


Yes, I agree. We don't have good reason to think this should be about class methods at all.


I wrote a longer reply earlier today, but I ran into the dreaded "invalid characters" forum error, so I can't post it. Basically, if the question is changed from "how to call" (not correct for object-oriented programming) to "how to send a message to", then it becomes clear that this requires a receiver of the message (an instance), and the OP hasn't faced the issue of what instances should exist, and how to keep track of them.

Well. I know. But if I use a instance method, I cannot call the method from another class. Let's say I want to make a pause button on GameViewController class that calls the method "pause" in GameScene class.

GameViewController.m

-(IBAction)pause:(id)sender{
    [GameScene pause];
}

GameScene.m

+(void)pause{
    SKNode *image = [self childNodeWithName@"Image"];
    [image removeActionForKey:@"Action"];
    [image removeActionForKey:@"Animation"];
]

I can't do it like this, right? So what can I do if I want to call method from another class. Do anyone has sample code. Please help me. Thanks

Again, as long as you think in terms of "call", you're never going to get anywhere. So, let's play "translations". You said:


>> I want to make a pause button on GameViewController class that calls the method "pause" in GameScene class


"Calls"? No, no. Let's translate that into this:


>> I want my Pause button action in my game view controller to send a "pause" message to my game scene.


That we can do! All you need is a reference to the game scene (that is, an instance of the GameScene class, not the GameScene class itself). How to get that reference? Well, if you started from Xcode's Game app template, your game view controller already has a "skView" property which is of type SKView, and SKView objects have a "scene" property, which is the game scene that's currently running. So, you can do something like this:


- (IBAction) pause: (id) sender { // GameViewController.m
     [self.skView.scene pause];
}


- (void) pause { // GameScene.m

    SKNode *image = [self childNodeWithName@"Image"]; 
    [image removeActionForKey:@"Action"]; 
    [image removeActionForKey:@"Animation"];
}


(Or something like that, depending on the details of your app so far.) Once you have a reference to the instance, it's easy.

You asked:

>if I use a instance method, I cannot call the method from another class.


You can. You need a reference to that instance method in the .h file of the Class and you need a reference to the instantiated Class.


Here's what you do:


#import "MyClass.h"
//your code executes this method (aka "calls" this method, aka "messages" this method)
-(void)someMethod{
   MyClass *anInstantiationOfMyClass=[[MyClass alloc] init];
    [anInstantiationOfMyClass theMethodInMyClass];
}


//then in MyClass.h you have:
@interface MyClass
-(void)theMethodInMyClass;
@end

// and in the MyClass.m file:
-(void)theMethodInMyClass{
      //  code here
}

Your answers helped me. They worked for me. Thanks. But my app still crash and I got this "Error loading image resource "image@%d.png" " and "Error loading image resource "sound.wav" ".

Actually I have image1, image2, ... to make animation and I write it in this way

SKSpriteNode *image = [SKSpriteNode spriteNodeWithImageNamed:@"image@%d"];

Any problem?

Sound

SKAction *soundPlay = [SKAction playSoundFileNamed:@"sound.wav" waitForCompletion:YES];
SKAction *repeatSound = [SKAction repeatActionForever:soundPlay];

Where to find the name which has to be written into "playSoundFileNamed"?" "? And to make sure it's correct? Please help. Thanks.