Count the number of times a method is called in Cocoa-Touch? - objective-c

I have a small app that uses cocos2d to run through four "levels" of a game in which each level is exactly the same thing. After the fourth level is run, I want to display an end game scene. The only way I have been able to handle this is by making four methods, one for each level. Gross.
I have run into this situation several times using both cocos2d and only the basic Cocoa framework. So is it possible for me to count how many times a method is called?

Can you just increment an instance variable integer every time your method is called?
I couldn't format the code in a comment, so to expound more:
In your header file, add an integer as a instance variable:
#interface MyObject : NSObject {
UIInteger myCounter;
}
And then in your method, increment it:
#implementation MyObject
- (void)myMethod {
myCounter++;
//Do other method stuff here
if (myCounter>3){
[self showEndGameScene];
}
}
#end

I don't know if your way is the best way to do it, or if mine is, but like Nathaniel said, you would simply define an integer to hold the count in your #interface:
#interface MyClass : NSObject {
int callCount;
}
Then the method can increment this by doing:
- (void) theLevelMethod {
callCount++;
// some code
}
Make sure you initialize the callCount variable to 0 though, in your constructor or the equivalent of viewDidLoad. Then in the code that checks the count you can check:
if (callCount == 4) {
// do something, I guess end scene
}
Then again, I guess you can simply do something like this:
for (int i = 0; i < 4; i++) {
[self theLevelMethod];
}
[self theEndScene];
I don't know how your game logic works, but I guess that would work.
Sorry if I misunderstood your question.

Related

In Objective-C is there a way to get a list of the methods called by a method?

I have been doing some research online and have found that using the ObjectiveC package in Objective C you can get a list of all the methods on a class using class_copyMethodList(), and I see you can get the implementation (IMP) of a method using instanceMethodForSelector:. The Apple documentation here has been helpful so far but I'm stuck and not sure what I'm really looking to find.
I want a list of the methods/functions called in a given method's implementation so I can build a call tree.
Any suggestions? Thanks in advance!
This solution is kind of hard way, and will cause a line of code in every method You can also make use of sqlite and save the tracked methods..
MethodTracker.h
#interface MethodTracker : NSObject
#property (nonatomic) NSMutableArray *methodTrackArr;
+ (MethodTracker *)sharedVariables;
#end
MethodTracker.m
#implementation MethodTracker
static id _instance = nil;
+ (MethodTracker *)sharedVariables
{
if (!_instance)
_instance = [[super allocWithZone:nil] init];
return _instance;
}
// optional
- (void)addMethod:(NSString *)stringedMethod
{
// or maybe filter by: -containObject to avoid reoccurance
[self.methodTrackArr addObject:stringedMethod];
NSLog("current called methods: %#", methodTrackArr);
}
#end
and using it like:
OtherClass.m
- (void)voidDidLoad
{
[super viewDidLoad];
[[MethodTracker sharedVariables] addMethod:[NSString stringWithUTF8String:__FUNCTION__]];
// or directly
[[MethodTracker sharedVariables].methodTrackArr addObject:[NSString stringWithUTF8String:__FUNCTION__]];
}
- (void)someOtherMethod
{
// and you need to add this in every method you have (-_-)..
[[MethodTracker sharedVariables] addMethod:[NSString stringWithUTF8String:__FUNCTION__]];
}
i suggest you import that MethodTracker.h inside [ProjectName]-Prefix.pch file.
Sorry, for the double answer, i deleted the other one and i have no idea how did that happen..
Hope this have helped you or at least gave you an idea.. Happy coding,
Cheers!
I think in the runtime track method is possible, but function not.
I have been build a tool DaiMethodTracing for trace all methods activity in single class for some of my need. This is based on objective-c method swizzling. So, there is an idea to do this
List all Classes in your application.
swizze all the methods in each class.
filter the method you want to trace.
finally, you may got the method call path.

Retrieving data from singleton in a more clever way ?

I have some game data in my GameStateSingleton, which I don't want to retrieve every time explicitly with [[GameStateSingleton sharedMySingleton]getVariable], so I asked myself whether it is possible to do something like that :
In the interface file of my class, GameLayer I set up properties and variables like sharedHealth.
#interface GameLayer : CCLayer
{
int sharedHealth;
}
#property (nonatomic,assign) int sharedHealth;
and of course synthesize it in the implementation.
#synthesize sharedHealth;
In the initialization of GameLayer I would like to do something like :
sharedHealth = [self getCurrentHealth];
and add the corresponding method
-(int)getCurrentHealth{
int myHealth = [[GameStateSingleton sharedMySingleton]getSharedHealth];
return myHealth;
}
Is that possible ? From what I have experienced, I just seem to get crashes. How would I achieve my goal, to not always have to call the long method, as it always retrieves the same variable? There has to be a solution for this ...
You don't need an instance variable for that. You could just write a shortcut function like this:
- (int)sharedHealth {
return [[GameStateSingleton sharedMySingleton] getSharedHealth];
}
And where ever you need that value, you call [self sharedHealth].
You could also use a preprocessor macro instead. Just define this:
#define SharedHealth [[GameStateSingleton sharedMySingleton] getSharedHealth]
And then simply use that when you need the value.
Note, that in Objective-C you don't call getter methods "getVariable", but simply "variable". Mostly this is a convention, but if you start using KVC or KVO it's a rule you have to follow. So it's better to get used to it as soon as possible.
If it's just the repetitive typing that you're trying to avoid, you could use the old C way...
#define GAME_STATE [GameStateSingleton sharedMySingleton]
...and then...
int localValue = [GAME_STATE property];

Variable out of IBAction

I have problem that im trying to get solve for like week.
My goal is to get variable out of my IBAction, to use for example in -(void)viewDidLoad..
But as far as I am now I can use my variable only in my IBAction..
- (IBAction) changeLat:(NSNumber *)str {
longi = str;
double lop = longi.doubleValue;
NSLog(#"%f",lop);
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog (#"%#",lop);
}
It NSLog shows everything fine in action, but in view did load it doesn't even recorganize it.
If you create a variable inside of -IBAction, the scope of that variable is only that method, so you cannot access to that variable outside it.
If you want your variable to be global to your class, you have to create it in the declaration of your class, like this:
#interface MainViewController () {
#private
double lop;
}
Put this at the beginning of your .m file, and then lop would be accesible in all your class.
You can read more about the scope of the variables here:
http://www.techotopia.com/index.php/Objective-C_Variable_Scope_and_Storage_Class
Actually, IBAction is converted to void by the preprocessor. It's used by Interface Builder as a label that identifies this method as an action able to be related from an IB Object.
There's no way (AFAIK) to use two return types in a function (for example `(IBAction double)´, equivalent to ´(void double)´), but a good practice could be something like this:
- (IBAction)changeLatAction:(id)sender {
NSNumber *str = <get the NSNumber from a valid place>;
[self changeLat:str];
}
- (double) changeLat:(NSNumber *)str {
longi = str;
double lop = longi.doubleValue;
NSLog(#"%f",lop);
return ????;
}
Your first declaration of changeLat seems to be wrong, because as a first parameter you'll always get the "sender" or "caller" object, related from IB (when called from an action, of course), so, you need to get the str value from a valid place.
Cheers.

Help with Wikibooks WikiDraw Obj-C application

I decided to start learning some Obj-C. And I thought that Wikibooks wikidraw application would be a good place to start (after some very basic "Hello World" programs). I've followed the chapters and now I'm at the end of "WikiDraws view class". So now I'm supposed to be able to compile and run. Of course it dosen't work. I got a lot of errors at first but i have fixed most of them, only 6 remaining. This is one of them:
- (void) mouseDragged:(NSPoint) pt
{
NSPoint np;
np.x = pt.x - _anchor.x;
np.y = pt.y - _anchor.y;
if ( _dragState == 0) {
// dragging of object
[self offsetLocationByX:np.x byY:np.y];
}
else if ( _dragState >= 1 && _dragState < 9 )
{
// dragging a handle
NSRect nb = [self newBoundsFromBounds:[self bounds] forHandle:_dragState withDelta:np];
[self setBounds:nb];
}
}
- (NSRect) newBoundsFromBounds:(NSRect) old forHandle:(int) whichOne withDelta:(NSPoint) p
{
// figure out the desired bounds from the old one, the handle being dragged and the new point.
NSRect nb = old;
switch( whichOne )
{ ..........
So at
NSRect nb = [self newBoundsFromBounds:...
I get an error message, "Invailid initializer" and "WKDShape may not respond to '-newBoundsFromBounds:forHandle:withDelta:"- . What should I do? I'm new to coding but eager to learn.
/Carl-Philip
Assuming you've pasted that code in the order written in your source code and newBoundsFromBounds:forHandle:withDelta: isn't declared (as distinct from being defined) at some earlier point, I think the problem is just that at nb = [self newBoundsFromBounds:... the compiler doesn't yet know what the return type will be. An NSRect is a C-style struct rather than an Objective-C class, so the compiler really does need to know.
As a solution, either put the definition of newBoundsFromBounds:... before mouseDragged:, add it to the #interface in your header file if you want it to be exposed to everyone or declare it internally to the implementation file as a category method. To do the final one, add the following to the top of your .m, assuming your class is called WikiDrawsView:
#interface WikiDrawsView (private)
- (NSRect)newBoundsFromBounds:(NSRect) old
forHandle:(int) whichOne
withDelta:(NSPoint) p;
#end
The 'private' is just a name you get to pick, it has no special meaning. Something like 'private' is often used to signify that you're using a category in a similar way that you might use private class member functions in C++ or a language like that.
The quick way to describe categories is that they patch additional methods onto existing classes at runtime, and they use the #interface [classname] ([category name]) syntax, with no member variable section. I'm sure your tutorial will get to them, Apple's documentation on them is here. This is a common use of categories but not the primary use.
To address the "WKDShape may not respond" warning, make sure you declare -newBoundsFromBounds:forHandle:withDelta: before -mouseDragged:. You can add it to the public interface in "WKDShape.h", or in an anonymous category in "WKDShape.m".

Creating global array & iterator

I am attempting to load up an entire array of NSManagedObjects into an NSArray, then use an integer iterator to iterate through the array when a button is tapped. xCode seems to dislike declaring the integer and NSArray in the .h, then used throughout different methods in the .m.
I was wondering what the appropriate path an experienced developer would take in solving such a problem.
The flow would be:
1. Load data into array.
2. Set label using information at index 0. int i = 0;
3. User taps button; i++, retrieve element at index 1.
and so on until the end of the array, or the user stops tapping the button.
Edited:
This is the code that works, but I feel is incorrect:
XYZViewController.h
#interface XYZViewController : UIViewController <NSFetchedResultsControllerDelegate>{
int index;
}
XYZViewController.m
import "XYZViewController.h"
- (void)function1{
index = 0;
}
- (void)function2{
index++;
}
-(void)function3{
NSManagedObject *obj = [results objectAtIndex:index];
}
Is this actually correct? It works, but not elegant; not at all.
Did you declare the integer and NSArray in your .h file outside of a class? if so, it would be defined in every compilation module that includes that file, which results in multiple symbols at linking time => error.
Solution: If you need the NSArray / int only in one .m file, move them there. Otherwise declare them as extern in the .h, and define them in exactly 1 .m file, like this:
// 1.h
extern int myInt;
// 1.m
#include "1.h"
int myInt;
// Use myInt
// 2.m
#include "1.h"
// Use myInt
The code you wrote is correct since you want to keep the visibility of the variable as private as possible. In this case it seems like you only need this variable in the XYZViewController.m file. In fact, you may want to consider prefixing it with #private to make it even less visible to other units.