get float value from nsdata objective-c iOS - objective-c

I am trying to get a float value from a NSData object which contains several hex values. e.g. EC 51 38 41
From this 4 Byte values i want to get the float value 11.52. How do i have to do this in xcode?
I have tried it with NSScanner (scanFloat, scanHexFloat), NSNumberformatter and NSNumber, i created an Byte Array and tried float myFloat = *(float*)&myByteArray. All these Options i found here at stackoverflow.
I tested it in Windows with C# and there it was no problem:
byte[] bytes = new byte[4] { 0xEC, 0x51, 0x38, 0x41 };
float myFloat = System.BitConverter.ToSingle(bytes, 0);
Does anybody know how i have to do this in xcode???
Thanks, Benjamin

When converting binary data from a foreign protocol always make sure to include proper swapping for endianness:
uint32_t hostData = CFSwapInt32BigToHost(*(const uint32_t *)[data bytes]);
float value = *(float *)(&hostData);
You have to know the endianness of the encoded data. You might need to use CFSwapInt32LittleToHost instead.

NSData * data = ...; // loaded from bluetooth
float z;
[data getBytes:&z length:sizeof(float)];
Try this.

I have tries it with NSScanner (scanFloat, scanHexFloat), NSNumberformatter and NSNumber
You're barking up the wrong tree here. NSScanner is for scanning strings. NSNumber is not the same as NSData, and NSNumberFormatter won't work with NSData either.
NSData is a container for plain old binary data. You've apparently got a float stored in an NSData instance; if you want to access it, you'll need to get the data's bytes and then interpret those bytes however you like, e.g. by casting to float:
float *p = (float*)[myData bytes]; // -bytes returns a void* that points to the data
float f = *p;

Related

How can I convert an iOS (objective-c) NSString value to a byte value?

How can I convert an iOS (objective-c) NSString value to a byte value?
JAVA uses .getBytes(), but I do not know how to do it on iOS.
uint8_t *dbytes = (uint8_t *)[Value bytes];
I expected to be something like this… but I do not want it.
You can call -[NSString UTF8String] to change NSString into const char*.
Example: const char *bytes = [Value UTF8String];
Reference: Apple Document
It is not clear in what encoding you expect your results to be.
Java's getBytes() returns String bytes using default encoding which is platform dependant, so instead use getBytes(charsetname) providing charset explicitly. You should communicate to use a specific encoding to avoid interoperability issues.
On iOS side, you can use -[NSStrings dataUsingEncoding:]
e.g.
NSData *bytes = [#"Hello" dataUsingEncoding:NSUTF8StringEncoding];
First, use UTF8String translate to unsigned long, then use 0xff & translate to Byte, as below:
NSString *str =#"xxx";
unsigned long red = strtoul([str UTF8String], 0, 16);
Byte bt = (Byte)(0xff & red);

Objective-C - NSData to integer does not work

I'm trying to convert 2 bytes in a NSData to an int.
Using the code
int value = *(int*)[d1 bytes];
NSLog(#"NSData: %# -> int: %d",d1, value);
i'll get
NSData: <01ac> -> int: 44033
which is int for ac01 not 01ac.
What would be the way to convert it in the correct way?
I believe that the byte order is switched (i.e. big endian vs. little endian).
To fix this, try:
int value = CFSwapInt32BigToHost(*(int*)[d1 bytes]);

Convert 1 byte to int Objective-C

I have an NSData packet with data in it. I need to convert the byte at range 8, 1 to an int. To get the data at that location I do the following.
NSData *byte = [packet subdataWithRange:NSMakeRange(8, 1)];
If I NSLog byte
<01>
How do I think convert this to an int? This is probably the most basic of questions but I am just not getting it right.
Any help would be appreciated.
Update
With that data the int should be equal to 1. I am not sure if this has anything todo with Endian.
use -[NSData bytes] to get raw buffer and read from it
int i = *((char *)[byte bytes])
or use -[NSData getBytes:length:]
char buff;
[bytes getBytes:&buff length:1];
int i = buff;
make sure you are reading from char * not int *, otherwise you are accessing invalid memory location, which may or may not crash or provide correct result.

How to store struct information on a uint64_t for Game Center challenges

I'm trying to store some game related information on the uint64_t context property of GKScore - to create a better gaming experience with the new Game Center Challenges. However, I'm not getting it right. I built a struct like below:
typedef struct{
unsigned int gameMode;
unsigned int destroyed;
unsigned int duration;
} GameInfo;
I try the following:
uint64_t myContext
GameInfo info;
info.gameMode = 2;
info.destroyed = 50;
info.duration = 100;
NSData *data = [NSData dataWithBytes:&info length:sizeof(info)];
[data getBytes:&myContext length:sizeof(myContext)];
to pack the struct to a NSData and then write the bytes to myContext.
Then, I try to recreate the information using the 64bit integer as follows:
NSData *newData = [NSData dataWithBytes:&myContext length:sizeof(myContext)];
GameInfo *result = (GameInfo*) [newData bytes];
however, when I log out the values, I see that I'm only able to capture the first two values (gameMode and destroyed). If I add more variables to the struct, I still only capture the first 2 variables.
What am I doing wrong? Is there a smarter way to do this?
You are trying to pack 96 bits of data (3 unsigned ints on iOS / ARM) into a 64 bit container. So you see the first two 32-bit values and not the third.
Maybe you could try using shorts or chars, depending on the range of values your struct will hold, and try to get the stuct's size down to < 64 bits. I think 3 char on ARM will get aligned out to 48 bits (might be wrong about that if so please let me know!). So maybe use short anyway.
EDIT: example of possible way to change your struct, assuming you'll only store 16-bit values in each field:
typedef struct{
uint16_t gameMode;
uint16_t destroyed;
uint16_t duration;
} GameInfo;

How to declare 2D byte array

I am trying to make a 2D byte array.
Can anybody give the code how to declare a NULL 2D byte array in Objective-C?
Since objective-c is a strict superset of c, you could just use a pure c definition and it would work fine:
char** myMatrix = malloc(width*height);
You could also use an NSArray of NSArrays, but that's not a 2 dimensional array. It's a jagged array and considerably less easy to use than a plain byte array.
Another alternative is using an NSData/NSMutableData object. That is the Foundation way of working with byte arrays. See NSMutableData class reference for more information.
NSMutableData* data = [NSMutableData dataWithLength:1024]; // One kilobyte
void* dataPointer = [data mutableBytes]; // Get a pointer to the raw bytes
I'm cheating by doing this in C.
size_t width;
size_t height;
unsigned char *twoDimArray = calloc(width*height);