NSString cString is Deprecated. What is the alternative? - ios

I've got another newbie question.
I've written a piece of code that converts a NSString to NSMutableData in order to simulate a webService result.
It turns out however that cString is deprecated. Can you help me replace it?
Here's my code.
NSString *testXMLDataString =
#"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
etc....
"</SOAP-ENV:Envelope>";
//Replace webData Received from the web service with the test Data
NSMutableData *testXMLData = [NSMutableData dataWithBytes:[testXMLDataString cString] length:[testXMLDataString length]];
[webData setData:testXMLData];

Get the raw bytes from the string.
Get the length of those bytes in the UTF8 encoding.
Create the NSData object using the +dataWithBytes:length: method.
const char *rawBytes = [testXMLDataString UTF8String];
const NSUInteger length = [testXMLDataString lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
NSAssert(length > 0, #"Couldn't convert to UTF-8");
NSMutableData *testXMLData = [NSMutableData dataWithBytes:rawBytes length:length];
[webData setData:testXMLData];

Related

Send hexString Data through UDP

I'm developing an iOS app. I've come across a problem.
I am trying to send a hexString data through UDP to an wifi camera, which will response while getting correct data. My code is shown below. However I can't get any response from my wifi camera. (I'm using
https://github.com/robbiehanson/CocoaAsyncSocket)
NSString *sendMsg = #"6745000005000000000000000000000000000000000000001400000067450000140000000A";
NSData *bytes = [sendMsg dataUsingEncoding:NSUTF16BigEndianStringEncoding];
NSString *host = #"255.255.255.255";
[self.udpSocket sendData:bytes toHost:host port:ListenPort withTimeout:-1 tag:1];
Beside, I've try send my data through PacketSender (an app can send UDP data), which has a correct response.
enter image description here
Problem has been solved. The problem is while converting NSString to NSData. It's hex string which need to convert to NSData. Below is my code which works.
- (NSData *)dataFromHexString:(NSString *)hexString {
NSAssert((hexString.length > 0) && (hexString.length % 2 == 0), #"hexString.length mod 2 != 0");
NSMutableData *data = [[NSMutableData alloc] init];
for (NSUInteger i=0; i<hexString.length; i+=2) {
NSRange tempRange = NSMakeRange(i, 2);
NSString *tempStr = [hexString substringWithRange:tempRange];
NSScanner *scanner = [NSScanner scannerWithString:tempStr];
unsigned int tempIntValue;
[scanner scanHexInt:&tempIntValue];
[data appendBytes:&tempIntValue length:1];
}
return data;}

IOS Core Bluetooth : Writing NSData for Characteristic

I am using the following code to write the 0xDE value for a Bluetooth Caracteristic (Reset Device) using the IOS Core Bluetooth :
...
NSData *bytes = [#"0xDE" dataUsingEncoding:NSUTF8StringEncoding];
[peripheral writeValue:bytes
forCharacteristic:characteristic
type:CBCharacteristicWriteWithResponse];
...
is there any mistake in my code because the value is not written properly?
Swift 3.0: In case anyone is wondering the format for Swift is slightly different as writeValue can get the count from the array.
let value: UInt8 = 0xDE
let data = Data(bytes: [value])
peripheral.writeValue(data, for: characteristic, type: .withResponse)
Try creating your data with an array of single byte values.
const uint8_t bytes[] = {0xDE};
NSData *data = [NSData dataWithBytes:bytes length:sizeof(bytes)];
This is a useful approach for creating arbitrary constant data. For more bytes,
const uint8_t bytes[] = {0x01,0x02,0x03,0x04,0x05};
NSData *data = [NSData dataWithBytes:bytes length:sizeof(bytes)];
If you want to create data to send using variables, I would recommend using NSMutableData and appending the bytes that you need. It isn't very pretty, but it is easy to read / understand, especially when you are matching a packed struct on the embedded side. Example below is from a BLE project where we were making a simple communication protocol.
NSMutableData *data = [[NSMutableData alloc] init];
//pull out each of the fields in order to correctly
//serialize into a correctly ordered byte stream
const uint8_t start = PKT_START_BYTE;
const uint8_t bitfield = (uint8_t)self.bitfield;
const uint8_t frame = (uint8_t)self.frameNumber;
const uint8_t size = (uint8_t)self.size;
//append the individual bytes to the data chunk
[data appendBytes:&start length:1];
[data appendBytes:&bitfield length:1];
[data appendBytes:&frame length:1];
[data appendBytes:&size length:1];
The answer by bensarz is almost correct. Except one thing: you shouldn't use sizeof(int) as the length for NSData. The size of int is 4 or 8 bytes (depending on the architecture). As you want to send 1 byte, use uint8_t or Byte instead:
uint8_t byteToWrite = 0xDE;
NSData *data = [[NSData alloc] initWithBytes:&byteToWrite length:sizeof(&byteToWrite)];
[peripheral writeValue:data
forCharacteristic:characteristic
type:CBCharacteristicWriteWithResponse];
Of courser you could also use int as the variable's type, but you have to initialize NSData with the length of 1.
This code will fix the problem :
NSData * data = [self dataWithHexString: #"DE"];
[peripheral writeValue:data forCharacteristic:characteristic
type:CBCharacteristicWriteWithResponse];
dataWithHexString implementation :
- (NSData *)dataWithHexString:(NSString *)hexstring
{
NSMutableData* data = [NSMutableData data];
int idx;
for (idx = 0; idx+2 <= hexstring.length; idx+=2) {
NSRange range = NSMakeRange(idx, 2);
NSString* hexStr = [hexstring substringWithRange:range];
NSScanner* scanner = [NSScanner scannerWithString:hexStr];
unsigned int intValue;
[scanner scanHexInt:&intValue];
[data appendBytes:&intValue length:1];
}
return data;
}
What you are, in fact, doing here is writing the string "0xDE" to the characteristic. If you want to use binary/octal notation, you need to stay away from strings.
int integer = 0xDE;
NSData *data = [[NSData alloc] initWithBytes:&integer length:sizeof(integer)];
[peripheral writeValue:data
forCharacteristic:characteristic
type:CBCharacteristicWriteWithResponse];

How can I convert NSData to C string?

How can I convert [NSString dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES] result to C string?
Returns an NSData object containing a representation of the receiver encoded using a given encoding.
- (NSData *)dataUsingEncoding:(NSStringEncoding)encoding allowLossyConversion:(BOOL)flag
Note that the data returned by dataUsingEncoding:allowLossyConversion:
is not a strict C-string since it does not have a NULL terminator.
NSMutableData *data = [[#"foo" dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES] mutableCopy];
char nul = '\0';
[data appendBytes:&nul length:sizeof(nul)];
const char *cString = [data bytes];
Or, simply:
const char *cString = [#"foo" UTF8String];
... with exactly the same result.
There is an -[NSString cStringUsingEncoding:] method that sounds promising.
It seems that you are asking the wrong question.
NSString* myString = #"Whatever";
const char* utf8String = [myString UTF8String];
Quite pointless to go through NSData.

How to Convert Nsdata to Unsigned or signed Byte array [duplicate]

This question already has answers here:
How to convert NSData to byte array in iPhone?
(6 answers)
Closed 9 years ago.
in my app i have to upload byte array(Audio ) to server .
BUt now We are getting Nsdata .How to convert this Nsdata to Byte array to post the Audio file to server
Can any one help me?
your can use bytes method of NSData;
NSUInteger len = [yourData length];
Byte *byteData = (Byte*)malloc(len);
memcpy(byteData, [yourData bytes], len);
If your byte is null terminated you can use
NSString *content = [NSString stringWithUTF8String:[yourData bytes]];
and if not
NSString *content = [[NSString alloc] initWithBytes:[yourData bytes]
length:[yourData length] encoding: NSUTF8StringEncoding];

Having an issue in encrypting/decrypting field in SQLite3

I am trying to encrypt/decrypt one field of SQLite3 database stored in iPhone app.
I am using this category mentioned in this question.
While encrypting, I am using following code:
NSString *key = #"pass123";
NSString *secret = webNote.note;
NSData *plain = [secret dataUsingEncoding:NSUTF8StringEncoding];
NSData *cipher = [plain AES256EncryptWithKey:key];
sqlite3_bind_text(statement, 1, [[cipher description] UTF8String], -1, SQLITE_TRANSIENT);
It does save data into the field in 74657874 20746f20 656e6372 797074 format.
But while decrypting, I get blank field (tried everything I knew). I am using following code for decrypting:
char *noteDet = (char *)sqlite3_column_text(statement, 1);
NSString *key = #"pass123";
NSString *secret = [NSString stringWithUTF8String:noteDet];
NSData *secretData = [secret dataUsingEncoding:NSUTF8StringEncoding];
NSData *clean = [secretData AES256DecryptWithKey:key];
aNote.note = ([[NSString alloc] initWithData:clean encoding:NSUTF8StringEncoding])?[[NSString alloc] initWithData:clean encoding:NSUTF8StringEncoding]:#"";
I think, I am unable to convert types. Please guide!
Thanks!
The description of NSData returns something like "" => if you were to read that again you would get different overall data ( and of a higher length ), also you are right that you are not converting the data types correctly.
Try saving the NSData object directly, by saving the bytes themselves rather than the description of the NSData object.
void *bytes = [dataObject bytes];
size_t length = [dataObject length];

Resources