【问题标题】:How to convert std::string to NSString?如何将 std::string 转换为 NSString?
【发布时间】:2011-04-02 21:43:22
【问题描述】:

您好,我正在尝试将标准 std::string 转换为 NSString,但运气不佳。

我可以使用以下代码从NSString 成功转换为std::string

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

但是当我尝试以下操作时出现编译时错误

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

我得到的错误是

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

我错过了什么吗?

提前致谢。

【问题讨论】:

  • 这一定是一个错字,但你在 'NSString *realm = "Hollywood";' 中缺少字符串文字的 '@'行。

标签: objective-c nsstring objective-c++ stdstring


【解决方案1】:

从 std::string 中获取 c-string 进行转换:

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

【讨论】:

  • 这似乎不是一个好的答案,正如文档所说:/* 用户相关编码,其值来自用户的默认语言和可能的其他因素。在没有其他提示的情况下,在解释具有未知编码的用户文档时,有时可能需要使用这种编码。这种编码应该很少使用,如果有的话。请注意,这里的一些潜在值可能会导致甚至相当简单的 NSString 内容的意外编码转换——例如,具有双向编码的标点符号。 */
  • [NSString stringWithUTF8String:mystring.c_str()] 似乎更合适,因为 std::string 更有可能来自您自己的代码,这很可能在 UTF8 中。
  • 你们知道为什么在这里 (developer.apple.com/documentation/foundation/nsstring/…) 它说“返回的对象可能与原始接收者不同”吗?这是什么意思,我们怎么知道它是否不同?
  • @cyrilchapier 如果我们的 .mm 文件显示“未指定特定编码”怎么办?
【解决方案2】:

首先,你必须使用 Objective-C++ 才能让它工作。确保这一点的最简单方法是将所有 *.m 文件重命名为 *.mm

到目前为止,将 C++ std::string 转换为 NSString 的最有用(非弃用)手动方法是:

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

这在大多数情况下都有效 - 如果您不进行特定的编码检测和转换,UTF-8 将为您提供一个很好的结果,让非拉丁字符“正常工作”。

但是,如果您正在制作一个更大的应用程序,或者您不是唯一一个在开发该应用程序的人,那么您可能会想要更容易应用的东西。

改编自cocoa-dev mailing list archives

@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

有了这个就地(并且适当地#imported),您现在可以:

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

std::wstring 也一样,非常方便。

【讨论】:

  • 这是 rad,我在几个 iphone 项目中使用过它。我注意到的一件事是,如果我正在运行 Apple 的单元测试框架并且我正在测试一个利用这些方法的库,我必须将包含字符串转换方法的文件作为“编译源”之一包含在“构建阶段”中单元测试。很奇怪。
  • 是的,单元测试本质上是它自己的小程序,并且需要访问相同的代码。此外,实际编写测试的荣誉;-)
  • 你们知道为什么在这里 (developer.apple.com/documentation/foundation/nsstring/…) 它说“返回的对象可能与原始接收者不同”吗?这是什么意思,我们怎么知道它是否不同?
  • @izzyMachado 文档中的这种语言通常意味着他们保留接口合同下的“权利”来解析、清理或规范化输入字符串。即它可能不是往返并且仍然比较==,而是他们可以做出的“最接近”或“最好”的表示。在这种情况下,接收者是 NSString 类实现,并且返回的值不是 Objective-C 对象,所以他们也可能用一些标准语言来覆盖它。
  • 你知道为什么当我们使用 initWithUTF8String 并且字符串包含非 utf8 字符时这仍然有效吗,它如何仍然能够使用字符串(如果它是薄荷 UTF-8)并打印出来一次成为一个 NSString ?
【解决方案3】:
NSString* mystring = [NSString stringWithUTF8String:stdstring.c_str()];

【讨论】:

  • 这会使 NSString UTF8 吗?或者 NSString 是什么编码?
【解决方案4】:

Apple 现在有了一种新的方式,他们希望您进行这种转换。在 XCode7 中,我使用 Edit > Convert > To Modern Objective C Syntax... 选项来找出答案。它使用简写@符号。

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

【讨论】:

  • 对不起,如果这是一个愚蠢的问题,但可以肯定的是,是否保证将 sCPPString.c_str() 复制到 sAppleString 中?我的意思是,如果 sCPPString 得分不够,那么 sAppleString 内的内存仍然有效吗?还有一个关于方法 stringWithUTF8String 和 stringWithCString 的问题,第一个是否复制,另一个只是指内存缓冲区,或者两者都保证复制? (我知道第一个复制,但另一个呢),我只是想确定一下。谢谢...
【解决方案5】:

我还发现:

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

像冠军一样工作。

【讨论】:

  • 这很不安全,也不能保证能正常工作。如果 std::string,standardString 是 C++ 对象。 C++ 对象对于传递给可变参数函数是不安全的(可变参数模板在 C++11 中解决了这个问题)。如果它有效,那是侥幸,几乎每个编译器都会至少警告你不要这样做(如果它不是一个错误开始的话)。
【解决方案6】:

这里是代码sn-p/example:

string str_simple = "HELLO WORLD";

//string to NSString
NSString *stringinObjC = [NSString stringWithCString:str_simple.c_str()
                                encoding:[NSString defaultCStringEncoding]];            
NSLog(stringinObjC);

【讨论】:

    猜你喜欢
    • 2011-12-21
    • 1970-01-01
    • 2019-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-07
    相关资源
    最近更新 更多