Làm thế nào để chuyển đổi std :: string sang NSString?


97

Xin chào, tôi đang cố gắng chuyển đổi một tiêu chuẩn std::stringthành mộtNSString nhưng tôi không gặp nhiều may mắn.

Tôi có thể chuyển đổi thành công từ an NSStringsang a std::stringbằng mã sau

NSString *realm = @"Hollywood";
std::string REALM = [realm cStringUsingEncoding:[NSString defaultCStringEncoding]];

Tuy nhiên, tôi gặp lỗi thời gian biên dịch khi thử những cách sau

NSString *errorMessage = [NSString stringWithCString:REALM encoding:[NSString defaultCStringEncoding]];

Lỗi tôi nhận được là

Cannot convert 'std::string' to 'const char*' in argument passing

Am i thiếu cái gì ở đây?

Cảm ơn trước.


4
Nó phải là một lỗi chính tả, nhưng bạn đang thiếu '@' cho chuỗi ký tự trong 'NSString * domains = "Hollywood";' hàng.
Vladimir

Câu trả lời:


111

Lấy c-string ra khỏi std :: string để chuyển đổi:

NSString *errorMessage = [NSString stringWithCString:REALM.c_str() 
                                   encoding:[NSString defaultCStringEncoding]];

Đây có vẻ không phải là một câu trả lời tốt, như tài liệu cho biết: / * Mã hóa phụ thuộc vào người dùng mà giá trị được lấy từ ngôn ngữ mặc định của người dùng và các yếu tố tiềm năng khác. Việc sử dụng mã hóa này đôi khi có thể cần thiết khi giải thích các tài liệu của người dùng có mã hóa không xác định, trong trường hợp không có các gợi ý khác. Bảng mã này hiếm khi được sử dụng, nếu có. Lưu ý rằng một số giá trị tiềm năng ở đây có thể dẫn đến chuyển đổi mã hóa không mong muốn của nội dung NSString thậm chí khá đơn giản --- ví dụ: các ký tự dấu chấm câu với mã hóa hai chiều. * /
cyrilchampier

30
[NSString stringWithUTF8String: mystring.c_str ()] có vẻ thích hợp hơn, vì chuỗi std :: nhiều khả năng đến từ mã của chính bạn, có thể là trong UTF8.
cyrilchampier

Các bạn có biết tại sao ở đây ( developer.apple.com/documentation/foundation/nsstring/… ) lại thông báo “Đối tượng trả về có thể khác với bộ thu ban đầu” không? Điều này có nghĩa là gì và làm thế nào chúng ta biết được nếu nó khác?
isJulian00

@cyrilchapier điều gì xảy ra nếu tệp .mm của chúng tôi cho biết “không có mã hóa cụ thể nào được chỉ định”?
isJulian00

53

Đầu tiên, bạn phải sử dụng Objective-C ++ để điều này hoạt động một cách nhỏ nhất; cách dễ nhất để đảm bảo rằng đổi tên tất cả các *.mtệp của bạn thành*.mm

Cho đến nay, cách thủ công hữu dụng nhất (không bị phản đối) để chuyển C ++ std::stringvào an NSStringlà với:

std::string param; // <-- input
NSString* result = [NSString stringWithUTF8String:param.c_str()];
NSString* alternative = [[NSString alloc] initWithUTF8String:param.c_str()];

Điều này sẽ hoạt động trong hầu hết các trường hợp - và nếu bạn không thực hiện phát hiện và chuyển đổi mã hóa cụ thể, UTF-8 sẽ cung cấp cho bạn một kết quả tốt để có các ký tự không phải latin 'chỉ hoạt động'.

Tuy nhiên, nếu bạn đang tạo ra một ứng dụng lớn hơn hoặc bạn không phải là người duy nhất làm việc trên ứng dụng đó - có thể bạn sẽ muốn thứ gì đó dễ áp ​​dụng hơn.

Phỏng theo kho lưu trữ danh sách gửi thư của nhà phát triển ca cao

@interface NSString (cppstring_additions)
+(NSString*) stringWithwstring:(const std::wstring&)string;
+(NSString*) stringWithstring:(const std::string&)string;
-(std::wstring) getwstring;
-(std::string) getstring;
@end

@implementation NSString (cppstring_additions)

#if TARGET_RT_BIG_ENDIAN
const NSStringEncoding kEncoding_wchar_t = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingUTF32BE);
#else
const NSStringEncoding kEncoding_wchar_t = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingUTF32LE);
#endif

+(NSString*) stringWithwstring:(const std::wstring&)ws
{
    char* data = (char*)ws.data();
    unsigned size = ws.size() * sizeof(wchar_t);

    NSString* result = [[NSString alloc] initWithBytes:data length:size encoding:kEncoding_wchar_t];
    return result;
}
+(NSString*) stringWithstring:(const std::string&)s
{
    NSString* result = [[NSString alloc] initWithUTF8String:s.c_str()];
    return result;
}

-(std::wstring) getwstring
{
    NSData* asData = [self dataUsingEncoding:kEncoding_wchar_t];
    return std::wstring((wchar_t*)[asData bytes], [asData length] / sizeof(wchar_t));
}
-(std::string) getstring
{
    return [self UTF8String];
}

@end

Với điều đó tại chỗ (và được chỉnh sửa phù hợp #import) bây giờ bạn có thể:

NSString* result = [NSString stringWithstring:param];
string convertedBack = [result getstring];

Và điều tương tự đối với std::wstring, điều này còn hơn cả tiện dụng.


1
Đây là rad và tôi đã sử dụng nó trong một vài dự án iphone. Một điều tôi nhận thấy là nếu tôi đang chạy khung kiểm tra đơn vị của Apple và tôi đang thử nghiệm một thư viện sử dụng các phương pháp này, tôi phải bao gồm tệp chứa các phương thức chuyển đổi chuỗi làm một trong những "Nguồn biên dịch" trong "Giai đoạn xây dựng" cho bài kiểm tra đơn vị. Kỳ dị.
David,

1
Đúng, bài kiểm tra đơn vị về cơ bản là một chương trình nhỏ của riêng nó và cần có quyền truy cập vào cùng một đoạn mã. Ngoài ra, thanh danh cho thực sự viết bài kiểm tra ;-)
rvalue

1
Các bạn có biết tại sao ở đây ( developer.apple.com/documentation/foundation/nsstring/… ) lại thông báo “Đối tượng trả về có thể khác với bộ thu ban đầu” không? Điều này có nghĩa là gì và làm thế nào chúng ta biết được nếu nó khác?
isJulian00

1
@izzyMachado rằng loại ngôn ngữ trong tài liệu thường có nghĩa là họ bảo lưu "quyền" theo hợp đồng giao diện để phân tích cú pháp, làm sạch hoặc chuẩn hóa chuỗi đầu vào. tức là nó có thể không khứ hồi và vẫn so sánh ==mà là đại diện "gần nhất" hoặc "tốt nhất" mà họ có thể thực hiện. Người nhận trong trường hợp này là NSStringtriển khai lớp và giá trị trả về không phải là một đối tượng Objective-C, vì vậy chúng cũng có thể bao gồm điều đó bằng một số ngôn ngữ chuẩn.
rvalue

Bạn có biết tại sao điều này vẫn hoạt động khi chúng tôi sử dụng initWithUTF8String và chuỗi bao gồm các ký tự không phải utf8, làm thế nào nó vẫn có thể sử dụng chuỗi (nếu là UTF-8 màu bạc hà) và in ra khi nó trở thành NSString?
isJulian00

21
NSString* mystring = [NSString stringWithUTF8String:stdstring.c_str()];

điều này có làm cho NSString trở thành UTF8 không? hoặc mã hóa NSString sẽ là gì?
isJulian00

14

Apple hiện có một cách mới mà họ muốn bạn thực hiện việc chuyển đổi này. Trong XCode7, tôi đã sử dụng tùy chọn Edit> Convert> To Modern Objective C Syntax ... để tìm ra điều này. Nó sử dụng ký hiệu viết tắt @.

std::string sCPPString = "Hello World!";
NSString *sAppleString = @(sCPPString.c_str());

3

Tôi cũng thấy rằng:

NSString *nsString = [NSString stringWithFormat:@"%s",standardString];

Hoạt động như một nhà vô địch.


3
Điều đó khá không an toàn và không đảm bảo hoạt động. standardString nếu một std :: string, là một đối tượng C ++. Các đối tượng C ++ không an toàn để chuyển đến các hàm khác nhau (các mẫu biến thể giải quyết vấn đề này trong C ++ 11). Nếu nó hoạt động thì đó là một sự may mắn và hầu hết mọi trình biên dịch ít nhất sẽ cảnh báo bạn không nên làm điều này (nếu nó không phải là một lỗi để bắt đầu).
Vitali

3

Đây là đoạn mã / ví dụ:

string str_simple = "HELLO WORLD";

//string to NSString
NSString *stringinObjC = [NSString stringWithCString:str_simple.c_str()
                                encoding:[NSString defaultCStringEncoding]];            
NSLog(stringinObjC);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.