Function injection in objective-c - objective-c

I have a random number generator (RNG) function.
-(double) generateRandomNumber
{
... do some stuff
return randomNumber;
}
I have a function that calls this random number generator function to do a task - something along the lines of
-(double) GenerateSellPrice {
double randomNumber;
randomNumber = [self generateRandomNumber];
return value*randomNumber;
}
I want to modify this so that the random number generator function is actually passed into the GenerateSellPrice function, so that I can swap in and out different RNGs for different purposes (i.e. unit testing, different ranges, etc).
How do I declare the RNG function so that it is in a form that I can pass it around (I'm assuming as a function pointer)? How do I declare the GenerateSellPrice to accept the function as a parameter? And how do I then invoke the function?

You could declare your PRNGs as Objective-C blocks and pass them around like any other object. http://www.mikeash.com/pyblog/friday-qa-2008-12-26.html has some info on the subject.

The classic Objective-C pattern would be to take a selector (SEL) and object (id) argument argument:
-(double) GenerateSellPriceWithRNG:(id)rngObject selector:(SEL)rngSelector
double randomNumber;
randomNumber = [rngObject performSelector:rngSelector];
return value*randomNumber;
}
and call it with
[self GenerateSellPrinceWithRNG:self selector:#selector(generateRandomNumber)];
Modern practice would probably take a block (double (^)()) parameter. The syntax for a block is slightly uglier, but the power it brings is useful in this scenario. You get better type-checking from the compiler and you can easily generate a block inline where convenient rather than having to write an entire class & method.
In this case you could declare
-(double) GenerateSellPriceWithRNG:(double (^)())rngBlock {
double randomNumber;
randomNumber = rngBlock();
return value*randomNumber;
}
and call it with
[self GenerateSellPriceWithRNG:^{ return [self generateRandomNumber]; }];
or with any other block that returns a double.

The easiest way to do that is to use the "selector" object. You can declare a selector by doing the following
#selector(generateRandomNumber)
Once you have a selector object, you use
SEL randomNumberFunction; // Most likely passed in as a parameter
NSObject *generatorObject;
[generatorObject performSelector:randomNumberFunction];

Worked it out using blocks. For those who want to know how I did it, I declared my RNG in my calling class (classA) as a class variable
double(^generateRandomNumber)(void) = ^{
...do stuff;
return randomNumber;
};
Then declared my function in my called class (classB)
-(double) generateSellPriceWithGenerator:(double(^)(void))generator {
double randomNumber;
randomNumber = generator();
return value*randomNumber;
}
And then simply called the function from classA like so
double (^func)(void) = generateRandomNumber;
double value = [classB generateSellPriceWithGenerator:func];

Related

Varying Return Type Objective-C or c

How can I have a method/function that can return any type? For example sometimes the type will need to be float and sometimes it will need to be NSString* so id won't work because float isn't an id. I am not opposed to doing it in a c or c++ function if it's easier.
The reason why I need a dynamic return type is because I'm using objc/runtime to get an Ivar.
I would like some_type to be able to anything:
- (some_type)getIvarWithName:(const char *)name in:(id)obj
{
Ivar ivar(class_getInstanceVariable(object_getClass(obj),name));
return (some_type)ivar;
}
Return a float wrapped in an NSNumber, then you can use the id return type.
To simplify it, you can even use boxing literals, for example:
return #(1.1f);
The first thing to think about is why you would need a function that can return any type. It really doesn't make sense because you wouldn't be able to assign the value to anything, since you don't know the type. Of course, the situation is different when dealing strictly with Obj-C objects, as the language utilizes unknown objects with the id keyword. Unknown objects are like mixing Honeycrisp apples with Macintosh apples (no pun intended), and what you are trying to do is like mixing Honeycrisp apples with airplanes! However, if you want a certain type returned based off of the parameters (such as returning int for int parameters and float for float parameters), then you can overload the functions. Otherwise, then only way that I know of to return absolutely anything would be a void pointer (void *). This would point to a chunk of data that could really be anything. But back to the original problem. What does it represent and how long is it? Good luck!
UPDATE: As other answers mention, you can wrap simple data types (int, float, etc.) in objects such as NSNumbers or NSValues, which will work for your case. But when extending to more general scenarios with complex types such as structs, these generally can't be wrapped in built-in classes. You would need to make your own class using Obj-C.
There is no polymorphism of that kind in Obj-C.
If you know in advance what will be returned then you could use to methods of course.
Retruning id would work when you use an NSNumber for the float value.
You could even introduce a response object that either carries a number or a string and provides (bool) isNumber and (bool) isString methods for later processing.
But what are you really up to? In which context are you using that and what do you really try to achieve. To me it sounds as if there may be better solutions available.
Ofcourse it's weird solution, but you have weird question.
You need enable objective-c++: rename .m-file to .mm
Then yours code will look something like that:
void weird_function(int a)
{
switch (a)
{
case 0: throw #"Hello";
default: throw a;
}
}
void some_code(int a)
{
try
{
weird_function(a);
}
catch (int a)
{
NSLog(#"Catch int: %d", a);
}
catch (NSString* str)
{
NSLog(#"Catch string: %#", str);
}
}
Yours method can be implemented something like that:
union ValueHolder
{
void* voidPtrValue;
int intValue;
float floatValue;
NSString* nssstringValue;
};
- (void)getIvarWithName:(const char *)name in:(id)obj
{
ValueHolder vh;
Ivar ivar = object_getInstanceVariable(obj,name, &vh.voidPtrValue));
if (NULL == ivar)
return;
const char* encoding = ivar_getTypeEncoding(ivar);
if (0 == strcmp(encoding, #encode(int)))
throw vh.intValue;
if (0 == strcmp(encoding, #encode(float)))
throw vh.floatValue;
if (0 == strcmp(encoding, "#\"NSString\""))
throw vh.nsstringValue;
}
I found that using a template in c++ works to have a custom type
The following code works best for my situation:
template <typename _type>
static inline _type & hookVar(id self, NSString*name)
{
Ivar ivar(class_getInstanceVariable(object_getClass(self),[name UTF8String]));
#if __has_feature(objc_arc)
void *pointer(ivar == NULL ? NULL : reinterpret_cast<char *>((__bridge void *)self) + ivar_getOffset(ivar));
#else
void *pointer(ivar == NULL ? NULL : reinterpret_cast<char *>(self) + ivar_getOffset(ivar));
#endif
return *reinterpret_cast<_type *>(pointer);
}
To call the function I just use something like:
NSWindow *win = hookVar<NSWindow*>(self, #"_window");

How to implement whileTrue control flow method with Obj-C Blocks?

Is it possible to implement something like a Smalltalk-style whileTrue: method in Objective-C using blocks? Specifically, instead of:
int count = 0;
while (count < 10)
{
NSLog(count);
count++;
}
I'd like to be able to do (via a wrapper on the bool primitive called OOBoolean) something like...
__block int count = 0;
[[OOBoolean booleanWithBool: count < 10] whileTrueDo: ^() {
NSLog(count);
count++;
}];
I'm having trouble understanding how this would be implemented though...
Here you have a couple of ideas,
Assuming your bool wrapper implements boolValue, a naive implementation could be:
-(void) whileTrueDo:(void (^)(void)) block{
while ([self boolValue]) {
block();
}
}
In order for the wrapper to change its bool value after each iteration, the block must be able to actually change the variable that is used to calculate the boolean condition. So, in your case, by setting the __block type modifier to count, and increasing count in each block execution, you should be able to make it work.
The problem is, if you create your wrapper by sending the evaluated condition, as you stated in your question, you wont be able to change its bool value in each iteration. So, I would change the way the wrapper is created and the whileTrueDo: naive implementation so the boolean wrapper uses an evaluation block.
__block int count = 0;
OOBooleanBlock evaluationBlock = ^BOOL{
return count < 10;
};
[[OOBoolean booleanWithBlock:evaluationBlock] whileTrueDo: ^() {
NSLog(count);
count++;
}];
//In OOBoolean
+(OOBoolean*) booleanWithBlock:(OOBooleanBlock) evaluationBlock{
//Instantiate, set the evaluationBlock ivar and return the ooboolean object.
}
-(void) whileTrueDo:(void (^)(void)) block{
while (self.evaluationBlock()) {
block();
}
}
Remember to use the __block type modifier, otherwise you will enter in an infinite loop.
I haven't tested this, I hope this helps you though.
Cheers

Good practice for downcasting return type of inherited functions

I have got a Matrix-Class from which a Vector-Class is derived from and for extra functionality and better usage I've got a Vector3-Class which is derived from the Vector class. My problem is now that the Vector-class implements a function for instance +normalizeVector: which returns a new allocated Vector-instance. The subclass Vector3 should inherit these two functions but an inheritance leads to the function-prototypes that return a Vector-instance and not a Vector3-instance. This is just how inheritance works but is there a good practice how to solve that problem? A naive solution is to create Vector3 als a new class which subclasses NSObject but I want that Vector- and Vector3-instances can interact easily.
Here an code-example:
#interface Vector : NSObject {
....
}
+(Vector*) normalizeVector:(Vector*)v; //returns a new allocated Vector-instance
-(Vector*) normalize; //normalizes itself and returns itself
-(Vector*) otherFunction;
#end
#interface Vector3 : Vector {
}
-(Vector3*) specialFunction;
#end
usage of that code:
Vector3 *v3 = ...;
[[v3 normalize] specialFunction]; //Compiler gives me a warning because Vector has no specialFunction. Cast would help
[[Vector3 normalizeVector:v3] specialFunction]; //Compiler gives me a warning and during runtime it will crash because a `Vector` doesn't implement specialFunction
a cast to Vector3 would help but is not nice to work with and that also fails with the static function +normalizeVector: because in that static function a Vector-instance is allocated and a pointer-cast doesn't help.
any ideas? or other approaches / other modeling ?
edit: Code for my static function normalizeVector which gets inherited by Vector3:
#implementation Vector
...
+(Vector*) normalizeVector:(Vector *)v
{
unsigned int dim = vector_max(v.cols, v.rows);
Vector *res = [[[Vector alloc]initAsColumnVectorWithDim:dim] autorelease];
[Vector normalizeVector:v destination:res]; // this does only the logic: calc length and divide each component by the len and store at the vector passed to destination
return res;
}
#end
You will notice that -init methods always return type id -(id)init {..} exactly becauase of this.
Also, instead of [Vector alloc] - as you have noticed you don't actually know what Class you are in at runtime (it could be a subclass), so instead just use [self alloc] where self is the current Class because you are in a Class method. So, if you do [Vector3 normalizeVector:v] self is Vector3 and if you do [Vector normalizeVector:v] self is Vector.
Try adjusting your +normailzeVector: method to
+ (id)normalizeVector:(Vector *)v {
unsigned int dim = vector_max(v.cols, v.rows);
id res = [[[self alloc] initAsColumnVectorWithDim:dim] autorelease];
[self normalizeVector:v destination:res];
return res;
}
Just a note, + (id)normalizeVector: is not a function and definitely not a static function. It is a class method, it just helps to get the terms right.
In this case I would make normaliseVector an instance method. So instead of
Vector *newV = [Vector normalizeVector:v];
call
Vector *newV = [v normalizeVector];
Then you can produce a different normalizeVector for Vector and Vector3
EDIT:
For [[v3 normalize] specialFunction]; there is a problem in that normalize can sometimes return an object that specialFunction does not work on - ie it only works if v3 is a Vector3. So in this case there is extra information you have so a cast would be needed or that Vector3 normailze differs from Vector's. In this case I would produce a cover method on Vector3 to call normalize] specialFunction] so that the cast is in Vector3 specific code.

Passing float "byref" in Objective C?

Is there a way to pass a float "byref" to a method in objective C? Here's an overview of what I've got:
method signature:
- (void) MyMethod: (float*) min max:(float*) max;
method:
- (void) MyMethod: (float*) min max:(float*) max
{
}
trying to invoke it:
float min1 = 0; float max1 = 0;
[self MyMethod: min:&min1 max:&max1];
I get the following warning, and the code abends when trying to invoke MyMethod:
warning: 'MyClass' may not respond to '+MyMethod:min:max:'
The signature for your method is declared as
- (void) MyMethod: (float*) min max:(float*) max
but you are calling it as
- MyMethod:min:max:
... which includes an extra 'min:' that's not in the declaration.
Try changing your calling code to
float min1 = 0; float max1 = 0;
[self MyMethod:&min1 max:&max1];
and see if that improves things.
However, I see that your error message complains about the signature '+ MyMethod:min:max:', which also suggests you're trying to send the message to the class rather than an instance of the class; you will have to rectify that.
Finally, method selectors in Objective-C code usually start with a lower-case letter; you might want to read up on common Objective-C naming conventions.

object_getInstanceVariable works for float, int, bool, but not for double?

I've got object_getInstanceVariable to work as here however it seems to only work for floats, bools and ints not doubles. I do suspect I'm doing something wrong but I've been going in circles with this.
float myFloatValue;
float someFloat = 2.123f;
object_getInstanceVariable(self, "someFloat", (void*)&myFloatValue);
works, and myFloatValue = 2.123
but when I try
double myDoubleValue;
double someDouble = 2.123f;
object_getInstanceVariable(self, "someDouble", (void*)&myDoubleValue);
I get myDoubleValue = 0. If I try to set myDoubleValue before the function eg. double myDoubleValue = 1.2f, the value is unchanged when I read it after the object_getInstanceVariable call. Setting myIntValue to some other value before the getinstancevar function above returns 2 as it should, ie. it has been changed.
then I tried
Ivar tmpIvar = object_getInstanceVariable(self, "someDouble", (void*)&myDoubleValue);
If I do ivar_getName(tmpIvar) I get "someDouble", but myDoubuleValue = 0 still! Then I try ivar_getTypeEncoding(tmpIvar) and I get "d" as it should be.
So to summarize, if typeEncoding = float, it works, if it is a double, the result is not set but it correctly reads the variable and the return value (Ivar) is also correct.
I must be doing something basic wrong that I cant see so I'd appreciate if someone could point it out.
object_getInstanceVariable is a confused little function. It is documented that the last parameter is a void ** parameter—that is, you pass the address of a void * variable and get a pointer to the instance variable—but it is implemented as if it was a void * parameter—that is, you pass the address of the variable that you want to hold a copy of the instance variable. The problem is that the implementation ignores the size of the instance variable and just does a pointer copy. So anything that's the same size as a pointer will work perfectly. If you're running on a 32-bit architecture, only the high 32 bits will be copied. (You should witness the same behavior with a long long instance variable as well.)
The solution is to use the primary API, key-value coding, using -valueForKey:.
The other solution: If you wanted to write a fixed version, say as a category for NSObject, it would look something like this:
#implementation NSObject (InstanceVariableForKey)
- (void *)instanceVariableForKey:(NSString *)aKey {
if (aKey) {
Ivar ivar = object_getInstanceVariable(self, [aKey UTF8String], NULL);
if (ivar) {
return (void *)((char *)self + ivar_getOffset(ivar));
}
}
return NULL;
}
#end
Then your code would look like this:
double myDoubleValue = *(double *)[self instanceVariableForKey:#"someDouble"];
What about using valueForKey:?
NSNumber * value = [self valueForKey:[NSString stringWithUTF8String:ivar_getName(tmpIvar)]];
NSLog(#"Double value: %f", [value doubleValue];
Note: this requires you to have a "someFloat" method. If you want to use setValue:forKey:, you'll also need the "setSomeFloat:" method. This is easily implemented by declaring the ivar as an #property and synthesizing it.