Reputation: 1317
I am tasked with converting some functions from Objective-C to Swift. We are using a C file to transfer files to a bluetooth device. Here is the Objective-C code that needs to be converted.
From the Objective-C file:
NSString *room_name = filename;
NSData* bytes = [room_name dataUsingEncoding:NSUTF8StringEncoding];
UInt8 buff_name[bytes.length+1];
memcpy(buff_name, [room_name UTF8String],[room_name lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1);
I am stuck on memcpy
for Swift and am not sure this is the safest method for what we are trying to do. Thank you.
Upvotes: 4
Views: 1085
Reputation: 17040
My condolences, as the code you were given is a bit of a mess. First, it makes an NSData
from room_name
, converting the string to UTF-8 in the process, but then it doesn't use that NSData
for anything other than to determine the size of a buffer, and then it converts the string to UTF-8 again and copies it into the new buffer. This is a lot more inefficient, both from a computational and a readability standpoint, than it needs to be.
If we were leaving this in Objective-C, we'd already want to clean up the code. However, in Swift, we can make this even cleaner, because String
has a really nice and simple method to get us a pointer to the string's UTF-8 representation:
filename.withCString { ptr in
// call whatever C-based functions expect a `const char *` pointer here
}
Note that the pointer you get here is immutable. If the C functions you're calling expect to be able to modify the buffer, you'll want to make a copy instead. There are a few ways to do this, but the easiest is probably just to:
guard var data = filename.data(using: .utf8) else {
// handle this error somehow
}
data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<Int8>) in
// call whatever C-based functions expect a `char *` pointer here
// (if you need `unsigned char *`, use `UInt8` instead of `Int8`)
}
Upvotes: 3