How do I convert NSString to const void - ios

I am currently having issues converting NSString to a const void *
Here is my code:
DoSomethingFunction:(const void *)parameter
[class DoSomeThingFunction:(const void *)passswordField.text]
Password field is a UITextfield. The value becomes null when I try and cast it.
I want passwordField.text to be a const void * so it can be used in the function.

It depends on function implementation. It can be like this:
NSString *string = #"text";
const void *parameter = CFBridgingRetain(string);
DoSomethingFunction(parameter);
If function has similar parameter handling
void DoSomethingFunction(const void *parameter) {
NSString *string = CFBridgingRelease(parameter);
NSLog(#"%#", string);
}

Try casting the result of one of the NSString's methods that return a C string:
– cStringUsingEncoding:
– getCString:maxLength:encoding:
– UTF8String
NSString Class Reference

Related

Getting an error on a qsort compare function

I'm using C++Builder 10.4.2 and having a problem with qsort. I rarely use qsort so I might be making a clumsy mistake. Array 'buffer' is a 2D 'char' array with more than 26,000 rows of single words.
This is the call:
qsort((void *)buffer,wordcount,sizeof(buffer[1]),sort_function);
This is the compare function:
int TForm::sort_function(const void *a, const void *b)
{
return( strcmp((char *)a,(char *)b) );
}
This is the error message. Notice that it's complaining about sort_function for 4th argument:
search.h(46): candidate function not viable: no known conversion from 'int (__closure *)(const void *, const void *)' to 'int (*)(const void *, const void *) __attribute__((cdecl))'
What is 'int (__closure *)'? Is there a way to fix my compare function?
__closure is a Borland compiler extension for obtaining a pointer to a non-static class method, without regard to the type of class being used. This is most commonly used in VCL/FMX components, which allow you to assign event handlers from any class you want, which is not something that standard C++ typically allows you to do.
qsort() expects a C-style function pointer in the 4th parameter. You can't get such a pointer to a non-static class method.
To solve this, you need to use either:
a standalone function
a static class method
a non-capturing C++ lambda (C++11 or higher only)
Since your sort_function() does not need access to your TForm object, declaring sort_function() as static would be the simplest fix:
// .h
class TForm
{
...
private:
static int sort_function(const void *a, const void *b);
void doSomething();
...
};
// .cpp
int TForm::sort_function(const void *a, const void *b)
{
return strcmp((const char *)a, (const char *)b);
}
void TForm::doSomething()
{
...
qsort(buffer, wordcount, sizeof(buffer[1]), sort_function);
...
}
However, it really should be a standalone function instead since it really has no relation to your TForm class at all:
// .cpp
static int sort_function(const void *a, const void *b)
{
return strcmp((const char *)a, (const char *)b);
}
void TForm::doSomething()
{
...
qsort(buffer, wordcount, sizeof(buffer[1]), sort_function);
...
}

variadic param method wrapper ios objective-c [duplicate]

I'm developing a static library that will be distributed to other developers, who may need debug statements. So I have several levels of logging.
In order to avoid constant appearance of
if(loggingLevelCurrentlySet >= loggingLevelWantedForThisInstance){
NSLog(#"log this");
}
I created a set of logging function wrappers. A simplified version looks like this:
void myLog(int logLevel, NSString *format, va_list args){
if((loggingLevelCurrentlySet >= logLevel)){
NSLogv(format, args);
}
}
void myLogLevel1(NSString *format, ...){
va_list args;
va_start(args, format);
myLog(1, format, args);
va_end(args);
}
void myLogLevel2(NSString *format, ...){
va_list args;
va_start(args, format);
myLog(2, format, args);
va_end(args);
}
etc.
But now, I want, from within myLog, access to the fully formated string to do something else with.
void myLog(int logLevel, NSString *format, va_list args){
NSString *fullString = [NSString stringWithFormat:format, args]; //crashes when args is anything but an empty list
CFStringRef cfsr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, format, args); //also crashes
//want to use the string here
if((loggingLevelCurrentlySet >= logLevel)){
NSLogv(format, args);
}
}
NSString *fullString = [[[NSString alloc] initWithFormat:format arguments:args] autorelease];
There is a method for that ;)
Although I suggest not to use functions, but some simple macro definitions:
#define myLogLevel1(format, ...) myLog(1, format, __VA_ARGS__)
#define myLogLevel2(format, ...) myLog(2, format, __VA_ARGS__)

Constant built from another constant not working

I am beginning to delve into iOS development, and am learning Objective C. My background is Java.
I'm attempting to create a simple console game, and have created the following constants:
#import <Foundation/Foundation.h>
static const NSString *ROCK = #"Rock";
static const NSString *PAPER = #"Paper";
static const NSString *SCISSORS = #"Scissors";
static const NSString *LIZZARD = #"Lizzard";
static const NSString *SPOCK = #"Spock";
static const NSArray *WEAPONS = #[SPOCK, ROCK, SCISSORS, LIZZARD, PAPER];
The trouble is that I get an error on the last line: Initializer element is not a compile-time constant.
I tried to figure out what this means -- the closest thing I could find was this question by Fred Collins, where he notes that "This happens because objects works [sic] at runtime." I'm still not entirely sure what the implication of this is -- how is this different from Java? (I can definitely do this in Java!)
Regardless, I need some way of initializing NSArray *WEAPONS, and I can't make the answers to Fred Collin's question work for me without adding another file. (He is using a class for his constants, where as my program is simple enough to be contained in the same file as the main method.)
One proper way to initialize the array is to do this:
static const NSString *ROCK = #"Rock";
static const NSString *PAPER = #"Paper";
static const NSString *SCISSORS = #"Scissors";
static const NSString *LIZZARD = #"Lizzard";
static const NSString *SPOCK = #"Spock";
static const NSArray *WEAPONS = nil;
+ (void)initialize {
WEAPONS = #[SPOCK, ROCK, SCISSORS, LIZZARD, PAPER];
}
The initialize class method is a special class method that will only be called once before any instance is ever created or before any method (class or instance) is ever called.
NSArrays are not allowed to be used like that and must be done inside a method. Most everything with the exception of the NSString is disallowed.
Try something like
static const NSString *ROCK = #"Rock";
static const NSString *PAPER = #"Paper";
static const NSString *SCISSORS = #"Scissors";
static const NSString *LIZZARD = #"Lizzard";
static const NSString *SPOCK = #"Spock";
static const NSArray *WEAPONS = nil;
- (void)init
{
WEAPONS = #[SPOCK, ROCK, SCISSORS, LIZZARD, PAPER];
}
The proper way is to do it in the init method of the object, or
static const NSArray *WEAPONS = #[#"SPOCK", #"ROCK", #"SCISSORS", #"LIZZARD", #"PAPER"];
but I would not recommend this one.

Return the result of the outer method from the block in Objective-C

I have a method that creates a block inside. Is it possible to return the result of the method from this block? Something like:
- (id)myFunction {
//some code here
BlockType myBlock = ^{
//some other code here
return someObject; //is it possible to return something for myFunction?
};
[someOtherObject methodWithBlock: myBlock];
}
Blocks can have a return type. Here's an example.
First you define a block type (optional, but convenient)
typedef NSString * (^BlockType)(NSString *name);
^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^
return type type name parameters
Then you can instantiate a block like follows
BlockType aBlock = ^ NSString * (NSString *name){
return [#"Hello " stringByAppendingString:name];
};
And use it
NSString *salutation = aBlock(#"Nikita");
NSLog(#"%#", salutation); // => Hello Nikita

iOS UnitySendMessage call parameter

I am writing the Objective-C part of a Unity project. In AppController.mm, I declared
extern void UnitySendMessage(const char *, const char *, const char *);
And I am calling this like,
- (void)callUnityObject:(const char*)object Method:(const char*)method Parameter:(const char*)parameter
{
UnitySendMessage(object, method, parameter);
}
But I have a Unity function that has to receive an int parameter.
So, if I call like this:
[self callUnityObject:"_iosManager" Method:"GiveDynamite" Parameter:"50"];
The app doesn't crash, but the call doesn't work and I am getting an output like this:
The best match for method GiveDynamite has some invalid parameter.
If I call like this:
[self callUnityObject:"_iosManager" Method:"GiveDynamite" Parameter:50];
The App is crashing.
How can I send this message from Objective-c to Unity?
I tried declaring a new method like this:
extern void UnitySendMessage(const char *, const char *, int);
But the app crashed and said that unity doesn't have a function declaration like that.
Thanks in advance.
According to:
void UnitySendMessage( const char * className, const char * methodName, const char * param )
You should pass char*:
[self callUnityObject:"_iosManager" Method:"GiveDynamite" Parameter:"50"];
On Unity class you should receive "string" param
void GiveDynamite(string dinamite) {
...
}
and then parse it to integer value, f.e:
dinamiteAmount = int.Parse(dinamite);

Resources