Call a NSDictionary Value as Method - objective-c

How can I can I call a function which name I stored as a value an an NSDictionary? Basically I need to typecast a String as a method name/call. Is this possible?
[thisCellContent objectForKey:#"callFunction"] //the object contains the function name to be called
//call this value as function, something similar to this ..
[self [thisCellContent objectForKey:#"callFunction"]]
Is something like this possible?

Not like this, but you can use the runtime/reflection:
NSString *s = [thisCellContent objectForKey:#"callFunction"];
SEL sel = NSSelectorFromString(s);
[self performSelector:sel withObject:nil];

I would suggest putting an Objective-C block into the dictionary. You can then call the block (and it can call other things if you like). Something like this:
//In code that sets up the dictionary
void (^thingToCall)() = [^{ /* any code you want to run here */ } copy];
[dictionary setObject:thingToCall forKey:#"callFunction"];
//In code that uses the dictionary
void (^thingToCall)() = [dictionary objectForKey:#"callFunction"];
thingToCall(); //call the block

Related

Can not call a helper function from another function

I have written a helper function
-(NSString*) rotatePattern: (NSString*) patternToRotate
{
int tempIndex = indexOfChar(patternToRotate,_SignatureChar);
if(tempIndex != 0)
{
NSString* secondPartString = [patternToRotate substringToIndex:tempIndex-1];
NSString* firstPartString = [patternToRotate substringFromIndex:tempIndex];
NSMutableString *finalString;
[finalString setString:#""];
[finalString appendString:firstPartString];
[finalString appendString:secondPartString];
return finalString;
}
return patternToRotate;
}
Now I trying to call this function from another static method using below three method it is giving me used of undeclared identifier rotatePattern or use of undeclared identifier self
_finalPattern = [rotatePattern: #"hello"];
OR
_finalPattern = [self rotatePattern: #"hello"];
OR
_finalPattern = [self.rotatePattern: #"hello"];
If you can, make rotatePattern a static method, then you can use it like
[self rotatePattern: #"hello"]; if its within the same class
or [ThatClassName rotatePattern: #"hello"]; if its called from another class (or this class, this is the more politically correct way to do it)
otherwise if you cant make this method static, you can try make the other one non-static.
if both of those are an issue, what you are trying to do is not possible, since calling an instance method without an instance of the class doesnt make sense.

How to pass ivar into a function and set it without losing the reference to the original object

I am passing an ivar (NSMutableArray) into some method. I was expecting that if I modify the object inside the function, it would be reflected outside the function, but in this case I need to set the object; something like the following:
- (void) someMethod:(SMResponseObject *)response onData:(NSMutableArray *)imAnIvar {
imAnIvar = [response objects];
//Some other stuff
}
But I noticed that the memory reference of imAnIvar inside the function changes when I set it, and given that, the actual ivar doesn't change. I understand that the problem is that I'm changing the reference of the object inside the method, so it stops pointing to the ivar and then it points to some other random memory direction.
I thought about one solution to this problem, and it can be to ensure that the ivar is not nil before calling the function and do something like this:
- (void) someMethod:(SMResponseObject *)response onData:(NSMutableArray *)imAnIvar {
NSMutableArray *data = [response objects];
[arrayForTableView removeAllObjects];
for(id element in data){
[imAnIvar addObject:element];
}
//Some other stuff
}
So I use the original object instead of setting it directly. The problem is that in order for this to work I need to ensure that the ivar is not nil, which I think is not clean, because I'll need to do something like this on every call to the method:
if(!_ivar){
//alloc it
}
So my question is: Is there a way to force the local scope variable to point to the original variable even if I'm setting it? if not, is there any cleaner way to make this work?
Do you mean this?
- (void)setFoo:(SomeClass **)objPtr
{
*objPtr = someOtherObject;
}
// call it as:
SomeClass *foo = someObject;
NSLog(#"Before: %#", foo);
[self setFoo:&foo];
NSLog(#"After: %#", foo);
Why not use a getter for the array so that you need not check for the array being nil while using it?
-(NSMutableArray *)iAmAnIvar {
if(_iAmAnIvar == nil) {
_iAmAnIvar = [NSMutableArray array];
}
return _iAmAnIvar;
}
And when you have to set a value to the array, as you mentioned in your question, you could use
[self.iAmAnIvar removeAllObjects];
[self.iAmAnIvar addObject:someObj];
I believe you can use the - (id)copy; function of NSObject
so your code might look like this:
- (void)someFunction:(NSString *)someArg
{
NSString *str = [someArg copy];
}

Objective-C Block Syntax

Obj-C blocks are something I'm just using for the first time recently. I'm trying to understand the following block syntax:
In the header file:
#property (nonatomic, copy) void (^completionBlock)(id obj, NSError *err);
In the main file:
-(void)something{
id rootObject = nil;
// do something so rootObject is hopefully not nil
if([self completionBlock])
[self completionBlock](rootObject, nil); // What is this syntax referred to as?
}
I appreciate the assistance!
Blocks are Objects.
In your case inside the method you are checking if the block is not nil and then you are calling it passing the two required arguments ...
Keep in mind that blocks are called in the same way a c function is ...
Below i have split the statement in two to let you understand better :
[self completionBlock] //The property getter is called to retrieve the block object
(rootObject, nil); //The two required arguments are passed to the block object calling it
Its a block property, you can set a block at runtime.
Here is the syntax to set
As it is void type, so within the class you can set a method by following code
self.completionBlock = ^(id aID, NSError *err){
//do something here using id aID and NSError err
};
With following code you can call the method/block set previously.
if([self completionBlock])//only a check to see if you have set it or not
{
[self completionBlock](aID, nil);//calling
}

Problem declaring and calling internal metthods

How do I declare and use small helper functions inside my normal methods ?
In on of my objective-c methods I need a function to find an item within a string
-(void) Onlookjson:(id) sender{
NSString * res = [[sender gstring] copy];
persInfoBirth.text = getKeyValue(res, #"Birth");
}
I came up with a normal C type declaration for helper function getKeyvalue like this
NSString * getKeyvalue(NSString * s, NSString * key){
NSString *trm = [[s substringFromIndex:2] substringToIndex:[s length]-3];
NSArray *list = [trm componentsSeparatedByString:#";"];
//....
NSString res;
res = [list objectAtIndex:1];
//...
return res;
}
Example input string in s:
s=#"{ Birth = "1910"; Death = "1936"; }";
Anyway I get an exception "unrecognized selector sent to instance" for any of the two first lines in the helper function
How do I declare helper functions that are just to be used internally and how to call them safely ?
regards
Martin
Is this the real code? Do you get zero errors and warnings from the compiler? You must not ignore compiler warnings and you should turn on the Static Analyser in addition to the standard warnings.
There are many things wrong with the above code, most of which are nothing todo with declaring and calling methods. There is no way the above code could compile so maybe it pasted incorrectly or something..
Anyway.. declaring and using methods. Why are using a c function? Unless you have a good reason why not use Objective-c ? If you do have a good reason to use a C function the your definition should be:-
NSString *getKeyvalue( NSString *s, NSString *key ){
...
}
note the arguments. As NSString instances reside in the heap (not on the stack) you always want to pass pointers to them.
You then need to put the declaration in the header file:-
NSString *getKeyvalue( NSString *s, NSString *key )
EDIT:
In Objective-c there is no distinction between normal methods and helper methods, there is only one kind, and you have aleray written one
- (void)onLookJson:(id)sender { .. }
Taking it apart..
All methods begin with + or –, indicating Class method or Instance method. As you are familiar with C++ i guess you know what this means.
(void) is the return type. ie this method doesn't return a value. If it did it might look like (float) or (NSString *) or (id).
onLookJson: is the method name and the method takes 1 argument. Notice that the ':' is actually part of the name. This method is never is any circumstance just 'onLookJson'. An argument must always follow the :, so a method that doesn't take any arguments must not have one.
Ex
- (NSString *)fullName { .. }
This is an instance method, for example of a Person Class, you would call it like:-
NSString *theName = [aPerson fullName];
So
a method name that takes no
arguments is like 'speak'
a method
name that takes 1 argument is like
'speakTo:'
a method name that takes 2
arguments is like 'speakTo: language:'
a method name that takes 3
arguments is like 'speakTo: language: volume:'
etc.
All that is left is to put in the argument types and names.
Your function definition:
NSString *getKeyvalue( NSString *s, NSString *key ){
would become..
- (NSString *)getValue:(NSString *)s key:(NSString *)key { .. }
again, you need to declare it in the header or you will get a compiler warning.
- (NSString *)getValue:(NSString *)s key:(NSString *)key;

Objective-C Blocks - use as an object

With reference to the code below, once a block has been put into an array, how could you take that block object and run the actual code in the block.
Another Question: If I call a method in a block like below, does that block encapsulate the code in that method or capture the signature of the method and call it that way?
-(void)blockCalledMethod
{
NSLog(#"Hello World");
}
-(void)programStart
{
NSArray * array = [[NSArray alloc] initWithObjects:[[^ { [self blockCalledMethod];} copy] autorelease],nil];
id pointerToBlock = [array lastObject];
}
Call it like this:
void (^pointerToBlock)(void) = [array lastObject];
pointerToBlock(); // because ^ {} is void(^)(void)
You cannot declare pointerToBlock as an id if you want to call it directly, because the compiler has to recognize it as a block type and not just an object.
If I call a method in a block like above, does that block encapsulate the code in that method or capture the signature of the method and call it that way?
I should think self refers to the calling class.