Calling another method from Cocos2d Hud layer - iphone

I have two class files hudlayer.m and actionlayer.m
I have a method named jump in hudlayer.m
And i have a method named jumpone in actionlayer.m
-(void) jumpone {
_heroBody->ApplyLinearImpulse(b2Vec2(_playerVelX/[_lhelper pixelsToMeterRatio], 1.25), _heroBody->GetWorldCenter());
}
and another method called jump in hudlayer.m
-(void)jump {
ActionLayer *aob = [[ActionLayer alloc] init];
[aob jumpone];
}
The problem is when i call the Jumpone method from actionlayer.m my sprite jumps (i.e method called)
My init method of action layer
- (id)initWithHUD:(HUDLayer *)hud
{
if ((self = [super init])) {
[self setupWorld];
}
return self;
}
But when i call jumpone via jump method in from hudlayer.m it fails and my app crashed.
Any help will be appreciated .thanks

the best solution for your problem is to add a tag to hudlayer & action layer
ex: hudlayer.tag=1;
actionlayer.tag=2;
and then just use getChildByTag like this:
[[[[CCDirector sharedDirector]runningScene] getChildByTag:1]jumpone];

Everytime you call jump it creates a new instance of you ActionLayer. And following that, you setup a new world and everything get tangled up. Furthermore its a memory leak.
Make you ActionLayer to an iVar of HUDLayer and call
aob = [[ActionLayer alloc] init];
in the HUDs init method.
Dont forget to release aob in dealloc of the HUDLayer

Related

Override method using runtime library

I need to override - (void)viewWillAppear:(BOOL)animatedfor all ViewControllers adding NSLog(#"blabla") in this method. I.e. after every call of viewWillAppear invokes implemented early realization of viewWillAppear + my NSLog message. Is it possible? If yes, please give me an advice.
Currently I have tried this code
#implementation RuntimeTest
IMP previusImp;
IMP newIMP;
- (void)ovverrideViewWillAppearInViewController:(Class)vcClass {
newIMP = class_getMethodImplementation([self class], #selector(viewWillAppear:));
Method viewWillAppearMethod = class_getInstanceMethod(vcClass, #selector(viewWillAppear:));
previusImp = method_setImplementation(viewWillAppearMethod, newIMP);
}
- (void)viewWillAppear:(BOOL)animated {
previusImp(self, #selector(viewWillAppear:), animated);
NSLog(#"log2");
}
#end
then I have
#implementation IRViewController2
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(#"log");
}
#end
My custom viewWillAppear invokes first, then viewWillAppear from IRViewController2. And after this my application crashes with EXC_BAD_ACCESS. What's wrong?
if you can't use a subclass because you want to do it globally, but also don't want to lose the old version of the method (so category override is out of the question) then you need to swizzle away the old method, put in your new method that then calls the old method... I have used something called JRSwizzle to perform this in the past, it makes it easy to swizzle without writing a bunch of runtime code.
if (![self jr_swizzleMethod:#selector(originalInit) withMethod:#selector(init) error:&err])
{
NSLog(#"unable to jr_swizzle methods, error: %#",err);
exit(EXIT_FAILURE);
}
if (![self jr_swizzleMethod:#selector(init) withMethod:#selector(myInit) error:&err])
{
NSLog(#"unable to jr_swizzle methods, error: %#",err);
exit(EXIT_FAILURE);
}
then your -myInit method can call -originalInit or whatever methods you are using.

After subclass in the viewDidLoad the [super viewDidLoad] gets called, but the methods do not get executed

I got a question about subclassing.
I start with my first view:
in my .h file:
#interface viewAController : UIViewController
in my .m file:
-(void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Begin view");
udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
NSError *error = nil;
if (![udpSocket bindToPort:12345 error:&error]) //check ff of dit werkt!
{
NSLog(#"F you");
return;
}
NSLog(#"Derde line");
if (![udpSocket beginReceiving:&error])
{
NSLog(#"Screw you!");
return;
}
}
Porting and beginreceiving goes well.
and then when I subclass viewAController:
#interface viewBController : viewAController
in my .m file:
-(void)viewDidLoad{
[super viewDidLoad];
}
I am expecting that my subclass [viewBController], will display all of the NSLogs, because Im calling the super viewDidLoad.
Instead it is saying: F you!
Oke I understand that I can only bind once to the port, BUT Im expecting an error message, this does not show.
So I delete the binding and then I get Screw you, apparently I cannot say beginreceiving when Im not binding to a port. Without these two methods it works just fine though, it is printing everything out of the parent.
QUESTIONS:
Should I bind? I actually only need to listen to port 12345, should I just implement this differently?
Should I work without bind and without beginreceiving? I think I prefer with binding so that I wont listen to all of my ports.
Why cant I do beginreceiving when I dont bind?
How can I show the error?? Cause it is not printing any errors ...
greetz
What you are doing is right.But i have only one question to ask whether you have added the object of derived ViewController to some View.
Unless you wont add it you wont get the didLoad Of your superclass get fired.
Check by adding the object of your derived View to SomeView.
This is wrong you are doing
NSLog("#Hi there!");
you have to use
NSLog(#"Hi there!");
And if this is a typo (I hope it is) you have to add your sub class to some where using add subview or pushing it.

Inheritance in Objective C

I have a main game class which renders the game using Open GL. Now I thought I could inherit from this class and then just call [super init] in its init method to get a copy of it. The plan was to make some modifications in the copy but as it seems this doesn't work.
The following is the header file of my class:
#import "GameView.h"
#interface CloneView : GameView {
}
-(id)initWithFrame:(CGRect)frame;
#end
And this is the Clone view class:
#implementation CloneView
-(id)initWithFrame:(CGRect)frame{
return [super initWithFrame:frame];
}
#end
If I set a break point in the init method in the GameView class it stops there. Thing is: my clone view doesn't get rendered, the screen stays black.
What am I missing? Thanks for your help!
Edit
Just for the record: I tried without implementing initFrame and got the same result. (as expected as the initFrame as above isn't doing anything apart from calling super)
Edit 2
I'm adding my clone to another view so I'm creating two Eagle contexts. Could that be the reason why it doesn't work?
If you are not adding anything in the init function of CloneView than you don't even have to rewrite it. You can just have your class inherit from GameView and it automatically copies it's init function.
This is from the apple docs
You should assign self to the value returned by the initializer because the initializer could return an object different from the one returned by the original receiver.
So Try doing this
-(id)initWithFrame:(CGRect)frame{
if(self = [super initWithFrame:frame] ) {
//Do whatever you need to do here.
}
return self;
}
This should fix your issue if you need to do something in your init method. Otherwise you can skip the init method altogether.
try doing this it may work..
return(self=[super initWithFrame:frame])
which ensures the super class method is copied properly to the current method
TNQ
I finally located the problem:
I needed to write a second init method. The problem was that the following code was being executed twice:
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)[super layer];
[eaglLayer setOpaque:YES];
m_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
if (!m_context || ![EAGLContext setCurrentContext:m_context]) {
printf("FAIL \n");
[self release];
return nil;
}
[Textures loadTexture];
if ([self createFramebuffer]) {
[self draw];
}
This code was in the initFrame method of the game class. I made a second init method that does not execute this code. Instead, this code is executed in the parent view class of the clone. Now it works, YAY!!
Thanks for trying to help me!

How to release several classes which have the same delegate?

(or even just one class with one delegate)
Say I have a class called DataGetter, which downloads a file from the web. It has a delegate method, which gets triggered when the file has been downloaded:
- (void) dataGetterFinished:(DataGetter *)dataGetter;
So somehere in my code I can set up several files to be downloaded like so:
// in AViewController.m
DataGetter *blueFile = [[DataGetter alloc] init];
blueFile.delegate = self;
[blueFile getData:#"http://example.com/blue-file"];
DataGetter *redFile = [[DataGetter alloc] init];
redFile.delegate = self;
[redFile getData:#"http://example.com/red-file"];
Using clang static analyzer, each alloc line above gets a 'potential leak of an object allocated on lineā€¦' error. So how would I release the object. It has to hang around because it has a delegate. So is it OK to release it as the last line of the dataGetterFinished method, like so
- (void) dataGetterFinished:(DataGetter *)dataGetter
{
// code
[dateGetter release];
}
...or should I be using autorelease somehow?
Technically, that works fine, however I would suggest keeping track of the different DataGetters in an NSMutableArray.
For example:
DataGetter *blueFile = [[DataGetter alloc] init];
blueFile.delegate = self;
[blueFile getData:#"http://example.com/blue-file"];
[dataGetters addObject:blueFile]; // dataGetters is an NSMutableArray declared in the .h
[blueFile release];
// Same for red
Then in the delegate method, simple remove the getter from the array:
- (void) dataGetterFinished:(DataGetter *)dataGetter
{
// code
[dataGetters removeObject:dataGetter];
}
The array takes care of retaining the object, and you don't get the analysis warning.
Just be sure to release dataGetters in the dealloc method.

calling a method of current class from a method of another class

I am working on a class A which has a method -(void)DoSmthing1. I am making a call to
another method-(void)DoSmthing2 in class B. Now after doing some operations in class B, the method is supposed to call back a method-(void)DoSmthing3 previous class.
How will i call a method of current class from another class?? Can someone please help me....
Thanks in advance
edit1::
My Code:
Class A
{
-(void) MethodA {
}
-(void) MethodB {
ClassB *clsB = [[ClassB alloc] init];
[clsB MethodC];
}
}
Class B
{
-(void)MethodC:(selector) {
//here i want to call MethodA of classA, and i will prefer if it is possible by sending the name of the method as selector in this method(methodC)
}
}
edit2::
Another example i want to do smthing like follwoing:
ClassB *b = [[ClassB alloc] nitWithTarget:self selector:#selector(methodfromClassA) object:nil];
Here i want to call a method of class A once some task in Class B is completed, and that too from class A.
I hope it is much clear now.
Edit3:
- (void)loadView {
AsyncConnection *async =[[AsyncConnection alloc] init];
[async getAsync:self callback:#selector(test1)];
}
above code is from first class
-(void)getAsync:(id)anObject callback:(SEL)selector {
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:anObject
selector:#selector(selector)
object:nil];
[queue addOperation:operation];
[operation release];
}
and above code is from second class. Here i want to call a method of first class which is passed as selector.
- (void)loadView {
AsyncConnection *async =[[AsyncConnection alloc] init];
[async getAsync:self callback:#selector(test1)];
}
Other class:
-(void)getAsync:(id)anObject callback:(SEL)selector {
NSInvocationOperation *operation = [[NSInvocationOperation alloc]
initWithTarget:anObject
selector:#selector(selector)
object:nil];
[queue addOperation:operation];
[operation release];
}
First, if you want to use the above pattern, remove the #selector() from #selector(selector). You already have the selector. Doing #selector(selector) will create the SEL named selector and not the selector passed in as the argument.
Next, this seems like an odd pattern to start with; it'll work, but any experienced Obj-C/iOS/Cocoa developer will get the willies looking at it. Since you wrote the AsyncConnection class, use the delegate pattern. I.e. in the class that implements loadView.
That is, in AsyncConnection.h:
#property(retain) ClassA *callbackHandler;
And then:
- (void)loadView {
AsyncConnection *async =[[AsyncConnection alloc] init];
[async setCallbackHandler: self];
}
Then, in AsyncConnection, you would refer to the callback handler directly as self.callbackHandler (or [self callbackHandler]).
It sounds like you would benefit from reading the introductory material: The Objective-C Programming Language and Cocoa Fundamentals Guide. Additionally, you should read up on the basics of object-oriented programming (there are dozens of overviews all over the web and Amazon).
Essentially, you're confusing a class (the blueprint for creating an object, in its most basic description) and an instance of a class (an actual "instantiated" object of a given class). Somewhere you're going to have to have a reference from one instance to another (like objectB = [[ClassB alloc] init]) to send a message (like [objectB doSomethingAnObjectOfClassBWouldDo]). You might accomplish this by storing the reference as an instance variable or inside a collection (array, dictionary, etc.) that is an instance variable of the class that needs to "remember" who it needs to talk to.
It's important to realize you're trying to walk before you've learned to crawl with this platform. The only cure is to study. A lot. Guided books help.
Then new approach:
Should be something like:
classB.h
classA *aObj;
#property(nonatomic, retain) classA *aObj;
classB.m
#synthetize aObj;
classA.m
// after init class b obj
[bOjb setAObj:self];
classB.m
[aObj whateverMethodOfClassA];
Let me know if not clear.
My sugestion, is that generally if you want to avoid a real mess and a nightmare to debug, you should use observers and notifications rather than this kind of cross methods calls.
Make class A an observer of a notification of class B:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(classA-method-name:) name:#"notification-name" object:class-B-object ];
And when ready in class-B notify class A with parms:
[[NSNotificationCenter defaultCenter] postNotificationName:#"notification-name" object:self];
Just an idea.
One option is to use the delegate pattern in Objective C. Have the object of class A pass itself to an object of class B to be the handler for certain methods.