Functions in Objective-C - objective-c

I am trying to write a function which returns a string created from two input strings;
but when I try the function declaration
NSString Do_Something(NSString str1, NSString str2)
{
}
the compiler gets sick. (Worked fine for a different function with int arguments.)
If I change the input arguments to pointers to strings, in also gets sick.
So how do I pass Objective-C objects into a function?

All Objective-C objects being passed to functions must be pointers. Rewriting it like this will fix your compiler error:
NSString *Do_Something(NSString *str1, NSString *str2) { }
Also, please keep in mind that this is a (C-style) function and not an instance method written on an Objective-C object. If you wanted this to actually be a method on an object it would probably look something like this:
NSString *doSomethingWithString1:(NSString *)str1 string2:(NSString *)str2 { }
I say "probably" because you can name it however you want.

Functions are perfectly fine in Objective-C (and in fact earn some of the language's benefits).
See my answer to C function always returns zero to Objective C, where someone was trying what you are and had a problem with the compiler assuming return type. The structure that I set up there is important when you are using functions, just like when you are using objects and methods. Be sure to get your headers right.
To be pedantic, you're using a function definition of:
NSString *DoSomething(NSString *str1, NSString *str2) {
// Drop the _ in the name for style reasons
}
And you should be declaring it in a .h file like so:
NSString *DoSomething(NSString *str1, NSString *str2);
Just like C.

that doesn't work for me. i've just declared in the .h:
NSString *myFunction(NSDecimal *value);
and i type in the .m:
NSString *myFunction(NSDecimal *value){
//code
}
but always i get an error saying expected '(' before '*' token
now is fixed. for some reason... sorry.

Related

Corrupted string when returning new string from objective-c to swift

I try to build a string from an enum in Objective-C:
+ (NSString *)getStringFromKey:(ITGenericNotification)key {
return [NSString stringWithFormat:#"notification%lu", (long)key];
}
This code worked really well for over a year
However when I try to call it from swift with:
let notificationKey = NSNotification.getStringFromKey(ITNotificationWithObject.DidChangedQuestion.hashValue)
I get a corrupted string :
What is happening ?
The value of ITGenericNotification seems to be correct,
ITGenericNotification is defined as typedef long ITGenericNotification; and is used as base type for an enum with typedef NS_ENUM(ITGenericNotification, ITNotificationWithObject)
And + (NSString *)getStringFromKey:(ITGenericNotification)key is implemented as a category to NSNotification
You probably want .rawValue, not .hashValue, to get the underlying
integer value of the enum.
(Also the debugger variables view is sometimes wrong. When in doubt,
add a println() or NSLog() to your code to verify the values of
your variables.)

Is there a way to reflectively call a function in Objective-C from a string?

Are there any Objective-C runtime functions that will allow me to get a function (or block) pointer from a string identifying the function? I need some way to dynamically find and invoke a function or static method based on some form of string identifying it.
Ideally this function should be able to exist in any dynamically loaded library.
Looking at Objective-C Runtime Reference, the best bet looks like class_getClassMethod, but there don't appear to be any function-related functions in this reference. Are there other raw C ways of getting a pointer to a function by name?
if you want to invoke some static objc method, you can make it as a class method of a class
#interface MyClas : NSObject
+ (int)doWork;
#end
and call the method by
[[MyClass class] performSelector:NSSelectorFromString(#"doWork")];
if you real want to work with C-style function pointer, you can check dlsym()
dlsym() returns the address of the code or data location specified by
the null-terminated character
string symbol. Which libraries and bundles are searched depends on the handle
parameter If dlsym() is called with the special handle RTLD_DEFAULT,
then all mach-o images in the process
(except those loaded with dlopen(xxx, RTLD_LOCAL)) are searched in the order they were loaded. This
can be a costly search and should be avoided.
so you can use it to find the function pointer base on asymbol name
not sure why you want to do this, sometimes use function table can do
typedef struct {
char *name,
void *fptr // function pointer
} FuncEntry;
FuncEntry table[] = {
{"method", method},
{"method2", method2},
}
// search the table and compare the name to locate function, you get the idea
If you know method signature you can create selector to it with NSSelectorFromString function, e.g.:
SEL selector = NSSelectorFromString(#"doWork");
[worker performSelector:selector];
You may be able to do what you want with libffi. But unless you are doing something like create your own scripting language or something like that where you need to do this sort of thing a lot. It is probable overkill
I've wondered the SAME thing.. and I guess, after having researched it a bit.. there is NOT a "standard C" way to do such a thing.. (gasp).. but to the rescue? Objective C blocks!
An anonymous function.. that can be OUTSIDE any #implementation, etc...
void doCFunction() { printf("You called me by Name!"); }
Then, in your objective-C method… you can somehow "get" the name, and "call" the function...
NSDictionary *functionDict = #{ #"aName" : ^{ doCFunction(); } };
NSString *theName = #"aName";
((void (^)()) functionDict[theName] )();
Result: You called me by Name!
Loves it! 👓 ⌘ 🐻

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 question: method won't return a string

This is my first question so please forgive me if it's obvious. I learned to program in Pascal a few years ago, so my terminology may be off. I've looked at a bunch of postings, but nothing seems to address my basic problem.
I have a lookup table that I use to convert decimals back into fractions. I am calling this method...
-(void) convertToFractions:(float *)float2 aString:(NSMutableString *) myString;
...with this..
[self convertToFractions:&float1 aString:outputFraction];
The idea is that float2 is the decimal that I pass to the method, and myString is the fraction returning.
This runs after the lookup:
myString = [NSString stringWithString:[[decimalInchArray objectAtIndex:x]objectAtIndex:1]];
NSLog(#"myString = %#",myString);
The log shows myString is the correct fraction i.e. myString is correctly displaying the fraction I want to return, but outputFraction is null.
I think it's a pointer issue. I tried *myString, but the compiler throws an error (incompatible types).
Any suggestions are really appreciated.
You want to change the output of your convertToFractions method from void to NSString.
It's returning null because the return type of your method, is void, so it returns nothing.
The return type of an Objective-C method is in the parenthesis, at the beginning of the method name.
Here,s an example, but I don't see where you define convertToString so, I'll use pseudocode.
- (NSString *) convertToFractions:(float *)float2{
NSString *fraction = *some code to lookup fraction from table;*
return fraction;
}
myString = [self convertToFractions:(float *)float2];
EDIT:
As others have suggested, you should give Objective-C a fresh look. I suggest you read this Objective-C Primer written by Apple.
Where do you define your outputFraction? Nowhere in the code above you mention it.
At a guess your conversion method is declared as (void) meaning it will not return anything. If you need it to return the result as a NSString declare it like
-(NSString*) convertToFractions:(float *)float2 aString:(NSMutableString *) myString;
And make sure you return an NSString before reaching the end of the method with
return MyNSStringVariable;
[EDIT]
I can see you are hoping that outputFraction will be returned by your method but that is not the case with Objective-C (not sure about Pascal). You are simply passing outputFraction as a second variable in your method.
So the "right" way of doing it would be to have a method
-(NSString*)convertToFraction:(float*)float2 {
...// Do your float to fraction calculation here
...// Make sure fraction is formatted as NSString
return YourFractionVariable;
}
Then you can assign the return value to a variable of your choice, for instance:
NSString *fraction = [self converToFraction:aFloatNumber];
NSLog (#"fraction is %#", fraction);
Cheers,
Rog
Why not just return the string?
- (NSString*)convertToFractions:(float)float {
//Bla bla do everything
return [myString autorelease]; //Autorelease is for memory-management
}
Btw: You seriously need to read into ObjC. Please don't try to use your old pascal-knowledge on ObjC. It's different, and your knowledge isn't really applicable.
I would recommend buying a book about ObjC or reading some good tutorials for it. (Apple itself has some very good ones)
If you don't want to return NSString from your method as others suggested you can pass a pointer to NSString pointer to your function (the same way you pass NSError** to some standard api callsm e.g. in NSFileManager methods). Your code will look something like:
NSString *outputFraction;
[self convertToFractions:&float1 aString:&outputFraction];
-(void) convertToFractions:(float *)float2 aString:(NSMutableString **) myString{
...
if (myString)
*myString = [NSString stringWithString:[[decimalInchArray objectAtIndex:x]objectAtIndex:1]];
}

sortUsingFunction and "void value not ignored as it ought to be"

In my objective c class, I'd like to sort an array like this:
NSArray *sorted = [unsortedArray sortUsingFunction: mySort context: NULL];
My sort function is implemented as:
NSInteger mySort(id one, id two, void *ctx) { return 1; }
When I build the program the compiler tells me:
error: void value not ignored as it ought to be
Now I think I know what the compiler is trying to tell me:
"I don't know what the heck "mySort" is so I will assume it returns 'void'. Oops, looks like you are trying to assign 'void' to a variable, nope can't do that. Try again."
Alright, Mr. compiler, what in the world to I have to tell you so you know the function prototype is NSInteger mySort(id, id, void*)? I tried putting that line in the class header file, before the "#interface", after, pretty much all over the place, but I can't get this to work.
Where/how do I have to declare the function prototype for my sort function?
Big thanks in advance,
Mark.
sortUsingFunction: is an NSMutableArray method that re-orders the array object and does not return a value. It looks like you're looking for sortedArrayUsingFunction:, an NSArray method that returns a sorted, autoreleased shallow copy of the array.