I am developing a bridge between C++ and Swift. So I need to convert C++ u32 string into swift String. Here is the problematic code:
int count = linesProvider->getDisplayLinesCount();
NSMutableArray *lines = [[NSMutableArray alloc] initWithCapacity:static_cast<NSUInteger>(count)];
for (int i = 0; i < count; ++i) {
std::u32string_view line = linesProvider->getDisplayedLineAt(i);
NSString* objCline = [[NSString alloc] initWithBytesNoCopy:(void*)line.data()
length:line.size() * sizeof(char32_t)
encoding:NSUTF32StringEncoding freeWhenDone:NO];
[lines addObject:objCline];
}
While debugging I found out, that objCline is nil. What am doing wrong?

Is your string data accepted if you use the
initWithBytes:variant of the method?The reason for the failure is either that you're supplying string data that
CFStringdoes not like (in which case the above copying variant would also fail), or thatCFStringsimply does not support UTF-32 as an internal representation, so they must always be copied. I suspect the latter.If you feel like finding out for sure, you can trawl through the source for an older version of the
CFStringCreateWithBytesNoCopy()function (which is what theNSStringultimately calls down to) here:https://opensource.apple.com/source/CF/CF-1151.16/CFString.c.auto.html
It calls down to the rather long
__CFStringCreateImmutableFunnel3()function, which will take a while to unpick. You could compile your own version of that function and step through it in the debugger to find out which condition is causing thereturn NULLin your case.(As an aside, I suspect the
…NoCopysemantics will be difficult to uphold safely in a general purpose Swift wrapper, so allowing the copy might be the better approach anyway - for example,CFStringassumes the memory that is passed in will never be modified, which of course is not necessarily true for a C++ string.)