How to check private members in objective C unit tests? - objective-c

Considering this class :
#interface SampleClass : NSObject {
NSMutableArray *_childs;
}
- (void)addChild:(ChildClass *)child;
- (void)removeChild:(ChildClass *)child;
#end
How can i test when i add a child if the _childs array contains one object without adding a property to access it (because i don't want allow client code to access the _childs array) ?

Create a #property for it in the class extension and use the property for all accesses, that way you are testing and using the same code.

I'm not sure I correctly understand your question, I parse it as: While implementing addChild:, how do I prevent to insert objects a second time into _childs ?
There are two ways: if the order of your elements doesn't matter then you should simply use a NSMutableSet instead of an NSMutableArray. In this case the set takes care of everything:
- (void)addChild:(ChildClass *)child
{
[_childs addObject:child];
}
If order is important, stick with the NSMutableArray and do it like this:
- (void)addChild:(ChildClass *)child
{
if ([_childs containsObject:child]) return;
[_childs addObject:child];
}

Just make a -(int)childCount method that returns the count of the array.

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];

What's the best way to create an object factory in objective-c?

I have a hierarchy of classes like this:
MyBox
|
|->ImageBox
|->GalleryBox
|->MovieBox
|-> ...
Each one identified by a string like #"image-box" or #"gallery-box" coming from an xml block like this:
<image-box><property1>value1</property1>...</image-box>.
So i decided to create a factory class, which can create for me the correct object given the xml block:
[BoxFactory.h]
#interface BoxFactory {
NSMutableDictionary* stringToClassMapping;
}
+(BoxFactory)sharedBoxFactory;
-(void)registerClass:(Class)clazz withKey:(NSString*)key;
-(MyBox*)getBoxFromXml:(NSString*)xmlBlock;
#end
[.m]
#import "BoxFactory.h"
#import "MyFantasticXmlLibrary.h"
BoxFactory* gInstance=nil;
#implementation BoxFactory
+(BoxFactory*)sharedBoxFactory {
if (gInstance==nil)
gInstance=[[BoxFactory alloc]init];
return gInstance;
}
-(id)init {
self=[super init];
stringToClassMapping=[[NSMutableDictionary alloc]initWithCapacity:10];
return self;
}
-(void)registerClass:(Class)clazz withKey:(NSString*)key {
[stringToClassMapping setObject:clazz forKey:key];
}
-(MyBox*)getBoxFromXml:(NSString*)xmlBlock {
NSString* key=[MyFantasticXmlLibrary getRootNodeName:xmlBlock];
return [[[stringToClassMapping objectForKey:key]alloc]initWithXml:xmlBlock];
}
#end
Now the problem is: where should the concrete classes call the registerClass:withKey: method? it seems like the correct place would be in the init method of the BoxFactory, but this means that the Factory must be modified for each class added, which is not scalable for big hierarchies.
I really would like to find a way to put the registration call in the concrete class itself, keeping a better organized code and less dependencies. But until now i didn't find a way to execute code when a class is loaded, without initing an instance of it.
Ok, i found it out 5 minutes after posting the question, but i still think it can help somebody so i'll leave it here:
There is a method +(void)load in NSObject called exactly when the class is loaded in the image, at the very start of the execution. So the best place to register the classes with their factory is the +(void)load method of the concrete class itself. For example:
#implementation ImageBox
+(void)load {
[[BoxFactory sharedBoxFactory]registerClass:[ImageBox class] withKey:#"image-box"];
}
-(id)initWithXmlBlock:(NSString*)xmlBlock {
[...]
I've got a few ideas:
Option 1: Change the XML
If you have control over the file format, you can then use NSClassFromString to get the Objective-C class to work with that way.
Option 2: Store you registration information in a .plist
If you store the mapping of Tag -> Class or Class -> Tag in a .plist, you can simply load that up at boot time with NSDictionary dictionaryWithContentsOfFile rather than have it all over the place in the code
Option 3: Attribute oriented approach
Decorate your classes with an property either via a category, or by protocol, this way you can query the object model at boot time and use Type Introspection to discover what classes are available and what their tags are. This avoids having to manage two things (plist and classes) and also avoids having to change the xml (sometimes a no-go because it isn't yours to muck with). It's a bit more heavy handed at boot time, but it may be an ok trade of depending on what you are doing.

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

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.

How to detect a property return type in Objective-C

I have an object in objective-c at runtime, from which I only know the KVC key and I need to detect the return value type (e.g. I need to know if its an NSArray or NSMutableArray) of this property, how can I do that?
You're talking about runtime property introspection, which happens to be something that Objective-C is very good at.
In the case you describe, I'm assuming you have a class like this:
#interface MyClass
{
NSArray * stuff;
}
#property (retain) NSArray * stuff;
#end
Which gets encoded in XML something like this:
<class>
<name>MyClass</name>
<key>stuff</key>
</class>
From this information, you want to recreate the class and also give it an appropriate value for stuff.
Here's how it might look:
#import <objc/runtime.h>
// ...
Class objectClass; // read from XML (equal to MyClass)
NSString * accessorKey; // read from XML (equals #"stuff")
objc_property_t theProperty =
class_getProperty(objectClass, accessorKey.UTF8String);
const char * propertyAttrs = property_getAttributes(theProperty);
// at this point, propertyAttrs is equal to: T#"NSArray",&,Vstuff
// thanks to Jason Coco for providing the correct string
// ... code to assign the property based on this information
Apple's documentation (linked above) has all of the dirty details about what you can expect to see in propertyAttrs.
Cheap answer: use the NSObject+Properties source here.
It implements the same methodology described above.
The preferred way is to use the methods defined in the NSObject Protocol.
Specifically, to determine if something is either an instance of a class or of a subclass of that class, you use -isKindOfClass:. To determine if something is an instance of a particular class, and only that class (ie: not a subclass), use -isMemberOfClass:
So, for your case, you'd want to do something like this:
// Using -isKindOfClass since NSMutableArray subclasses should probably
// be handled by the NSMutableArray code, not the NSArray code
if ([anObject isKindOfClass:NSMutableArray.class]) {
// Stuff for NSMutableArray here
} else if ([anObject isKindOfClass:NSArray.class]) {
// Stuff for NSArray here
// If you know for certain that anObject can only be
// an NSArray or NSMutableArray, you could of course
// just make this an else statement.
}
This is really a comment addressing an issue raised by Greg Maletic in response to answer provided by e.James 21APR09.
Agreed that Objective-C could use a better implementation for getting these attributes.
Below is a method I quickly threw together to retrieve attributes of a single object property:
- (NSArray*) attributesOfProp:(NSString*)propName ofObj:(id)obj{
objc_property_t prop = class_getProperty(obj.class, propName.UTF8String);
if (!prop) {
// doesn't exist for object
return nil;
}
const char * propAttr = property_getAttributes(prop);
NSString *propString = [NSString stringWithUTF8String:propAttr];
NSArray *attrArray = [propString componentsSeparatedByString:#","];
return attrArray;
}
Partial list of attribute keys:
R Read-only
C Copy of last value assigned
& Reference to last value assigned
N Nonatomic property
W Weak reference
Full list at Apple
You can use isKindOfClass message
if([something isKindOfClass:NSArray.class])
[somethingElse action];
If you know that the property is defined :
id vfk = [object valueForKey:propertyName];
Class vfkClass = vfk.class;
And compare with isKindOfClass, isSubClass, etc.