How to convert Objective-C NSData to Swift Data? - ios

I have a NSData in Objective-C, the NSData has value 0x10, code like bellows:
#implementation BufUtil
+ (NSData *_Nonnull) getOCBuf {
std::vector<uint8_t> sendData = {0x10};
NSData * reqBuf = [[NSData alloc] initWithBytesNoCopy:sendData.data() length:sendData.size() freeWhenDone:false];
NSLog(#"getOCBuf, oc NSData reqBuf:%#", reqBuf);
return reqBuf;
}
#end
Then I use the data in Swift, Swift auto convert Objective-C NSData to Swift Data, but strange things happen, the value in Swift Data is 0x60, code like belows:
public func getOCBuf() -> Data {
let data = BufUtil.getOCBuf();
print("getOCBuf: swift data: \(data.hexEncodedString())")
return data
}
the log is like:
getOCBuf, oc NSData reqBuf:{length = 1, bytes = 0x10}
getOCBuf: swift data: 60
Now I am confused with what happened. Why 0x10 turn into 0x60, the two number not Binary complement.
Can anybody help me, thanks.
the code:
https://github.com/oncealong/SwiftOcDataConvert

It's my falut.
I copy code "how to convert from std::vector to NSData" from stackoverflow, but the code use [NSData alloc] initWithBytesNoCopy, which lead to all this.
the momory associate with the std::vector has freed after the getOCBuf func return. but the oc NSData and swift Data don't know. it use the origin address and found different value.
To be honest, the app should be crashed, and give a reason.

Related

How to get Bytes from swift Data

in my app I've to create some packet to send directly via network to an external device. I'm trying to create the packet.
In Objective-C I made something like this:
NSString *string = #"0021";
NSData *lengthData = [string dataUsingEncoding:NSNonLossyASCIIStringEncoding];
[data appendBytes:[lengthData bytes] length:[lengthData length]];
so in swift I made something like this:
let string = "0021"
let lengthData = string.data(using: String.Encoding.nonLossyASCII, allowLossyConversion: false)
data.append(lengthData?.bytes, count: pkt.length)
but the compiler says Cannot convert value of type 'UnsafeRawPointer?' to expected argument type 'UnsafePointer<UInt8>', can someone help me to fix this?
Thank you
In Swift you can just append the data (assuming data is Data and var)
if let lengthData = string.data(using: .nonLossyASCII) {
data.append(lengthData)
}

how to convert std::string to NSData and vice versa?

I am using google protocol buffer to send and receive data in cocos2d-x multiplayer game via Google Play Games Services iOS sdk.
Protocol buffer converts data to std::string but GPGS iOS sdk sends data via NSData hence I have to convert from std::string to NSData and then back to std::string after receiving data.
I am currently using following method:
(std::string to NSData and NSData to std::string will be done in different functions at different times. Following code just summarise what I am doing overall)
//PlayerData is protocol buffer class
PlayerData data, temp;
std::string dataStr;
data.SerializeToString(&dataStr);
NSString* nsDataStr = [NSString stringWithCString:dataStr.c_str()
encoding:[NSString defaultCStringEncoding]];
NSData* nsData = [nsDataStr dataUsingEncoding:NSUTF8StringEncoding];
NSString* dataStr_2 = [[NSString alloc] initWithData:nsData
encoding:NSUTF8StringEncoding];
std::string foo = [dataStr_2 UTF8String];
temp.ParseFromString(foo);
Initial string i.e dataStr after serializing
"\r\x95n\x99D\x158\xddNDJ\nUmar SaeedR\x12p_CPH64oqq2K-TXxAB"
size: 42
Final string i.e foo before parsing
"\r\xc3\xafn\xc3\xb4D\x158\xe2\x80\xbaNDJ\nUmar SaeedR\x12p_CPH64oqq2K-TXxAB"
size: 46
the ParseFromString function of protocol buffer does not parse foo and returns false.
How to do string conversions so that string remains same?
I know this is old, but... Could you use protobufs ParseFromArray instead of ParseFromString?
IE
const void *bytes = [parseData bytes];
int byteLen = (int)[parseData length];
protobufMessage.ParseFromArray(bytes, byteLen);
Just a thought.
Try this:
std::string str = "123";
NSData *data = [NSData dataWithBytes:str.data() length:str.length()];

How to Convert NSValue to NSString

Some background... I am writing code that interacts with javascript via a ObjC-JS bridge utilizing UIWebView's stringByEvaluatingJavaScriptFromString:. The idea is that the "brains" of the app be in JS which tells Objective-C how to behave. There are multiple benefits to this like reduced binary size, flexible updates, etc. However, there is a case where there is some Objective-C only object that the JS needs to have a reference to (JS instructs ObjC when to use/remove the object). This is being done by placing the native object in a dictionary with a unique identifier which can be passed as a string to JS (over the bridge). My problem stems with coming up with a nice identifier for said native Objective-C object.
Thus, I am trying to convert a reference to an object to a string with no luck. This is what I have:
// anObject is a custom class
NSValue *handle = [NSValue valueWithPointer:(__bridge const void *)anObject];
NSData *data = [NSData dataWithValue:handle];
NSString *stringHandle = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
The dataWithValue: function (taken from this SO post):
+ (NSData *)dataWithValue:(NSValue *)value {
NSUInteger size;
const char* encoding = [value objCType];
NSGetSizeAndAlignment(encoding, &size, NULL);
void* ptr = malloc(size);
[value getValue:ptr];
NSData* data = [NSData dataWithBytes:ptr length:size];
free(ptr);
return data;
}
Walking through it in the debugger shows me a nil value for stringHandle:
What am I doing wrong?
What you're doing wrong is trying to treat an address as if it's a UTF-8 encoded string. An address -- or any other chunk of arbitrary data -- isn't very likely to be valid UTF-8 data. (If by chance it were, it still wouldn't be the string you expect.)
If you're trying to get a string containing the pointer value, i.e., the address of the original object, that's just [NSString stringWithFormat:#"%p", anObject];
If you really need to do it from the NSValue, then replace anObject with [theValue pointerValue].
If you want to pretty-print arbitrary data, see How to convert an NSData into an NSString Hex string?
You can get a string representation by calling the NSObject method "description". You can override the "description" method in a subclass if you need.
An NSValue of a pointer will be an object holding the 4 bytes of the 32-bit pointer. It will not hold any of the data pointed to in RAM.

Obfuscating a number(in a string) Objective C

I'm using the following code to obfuscate a passcode for a test app of mine.
- (NSString *)obfuscate:(NSString *)string withKey:(NSString *)key
{
// Create data object from the string
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
// Get pointer to data to obfuscate
char *dataPtr = (char *) [data bytes];
// Get pointer to key data
char *keyData = (char *) [[key dataUsingEncoding:NSUTF8StringEncoding] bytes];
// Points to each char in sequence in the key
char *keyPtr = keyData;
int keyIndex = 0;
// For each character in data, xor with current value in key
for (int x = 0; x < [data length]; x++)
{
// Replace current character in data with
// current character xor'd with current key value.
// Bump each pointer to the next character
*dataPtr = *dataPtr++ ^ *keyPtr++;
// If at end of key data, reset count and
// set key pointer back to start of key value
if (++keyIndex == [key length])
keyIndex = 0, keyPtr = keyData;
}
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
This works like a charm with all strings, but i've ran into a bit of a problem comparing the following results
NSLog([[self obfuscate:#"0000", #"maki"]); //Returns 0]<W
NSLog([[self obfuscate:#"0809", #"maki"]); //Returns 0]<W
As you can see, the two strings with numbers in, while different, return the same result! Whats gone wrong in the code i've attached to result in the same result for these two numbers?
Another example:
NSLog([self obfuscate:#"8000" withKey:#"maki"]); //Returns 8U4_
NSLog([self obfuscate:#"8290" withKey:#"maki"]); //Returns 8U4_ as well
I may be misunderstanding the concept of obfuscation, but I was under the impression that each unique string returns a unique obfuscated string!
Please help me fix this bug/glitch
Source of Code: http://iosdevelopertips.com/cocoa/obfuscation-encryption-of-string-nsstring.html
The problem is your last line. You create the new string with the original, unmodified data object.
You need to create a new NSData object from the modified dataPtr bytes.
NSData *newData = [NSData dataWithBytes:dataPtr length:data.length];
return [[NSString alloc] initWithData:newData encoding:NSUTF8StringEncoding];
But you have some bigger issues.
The calls to bytes returns a constant, read-only reference to the bytes in the NSData object. You should NOT be modifying that data.
The result of your XOR on the character data could, in theory, result in a byte stream that is no longer a valid UTF-8 encoded string.
The obfuscation algorithm that you have selected is based on XORing the data and the "key" values together. Generally, this is not very strong. Moreover, since XOR is symmetric, the results are very prone to producing duplicates.
Although your implementation is currently broken, fixing it would not be of much help in preventing the algorithm from producing identical results for different data: it is relatively straightforward to construct key/data pairs that produce the same obfuscated string - for example,
[self obfuscate:#"0123" withKey:#"vwxy"]
[self obfuscate:#"pqrs" withKey:#"6789"]
will produce identical results "FFJJ", even though both the strings and the keys look sufficiently different.
If you would like to "obfuscate" your strings in a cryptographically strong way, use a salted secure hash algorithm: it will produce very different results for even slightly different strings.

Want to create byte array in objective c

i want to create a byte array in objective c, i am not able to find equivalent code of java's ByteArrayOutputStream and DataOutputStream.
for eg..
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeLong(counter); //counter is a long data type for eg 1165620611
dos.flush();
byte[] data = bos.toByteArray();
return data;
this code actually returns eight byte array...Here's the output in java
[0,0,0,0,69,121,-11,-125]
this is what i want exactly in objective c..
// #1 long to char array
long l = 1165620611;
char bytes[sizeof(long)];
memcpy(bytes,&l,sizeof(l));
// #2 char array to nsdata
int size = sizeof(bytes)/sizeof(char);
NSData *data = [NSData dataWithBytes:bytes length:size];
// #3 nsdata to char array
char buffer[size];
[data getBytes:buffer length:size];
// #4 prints char array: 0 0 0 0 69 121 -11 -125
while (0<size--) {
NSLog(#"%d",buffer[size]);
}
NSData is not needed at all, you can skip steps #2 and #3.
use char buff[] array in objective - c
You can use NSData & NSMutableData classes for this.
NSData and its mutable subclass NSMutableData provide data objects,
object-oriented wrappers for byte buffers. Data objects let simple
allocated buffers (that is, data with no embedded pointers) take on
the behavior of Foundation objects.
NSData creates static data objects, and NSMutableData creates dynamic
data objects. NSData and NSMutableData are typically used for data
storage and are also useful in Distributed Objects applications, where
data contained in data objects can be copied or moved between
applications.
The size of the data is subject to a theoretical limit of about 8
ExaBytes (in practice, the limit should not be a factor).
NSData is “toll-free bridged” with its Core Foundation counterpart,
CFDataRef. See “Toll-Free Bridging” for more information on toll-free
bridging.

Resources