使用std::string隐式构造NSString

Implicitly construct NSString with std::string

本文关键字:NSString std string 使用      更新时间:2023-10-16

在使用Objective-C++时,我经常发现自己使用initWithCString将std::string转换为NSString。为了简化这个过程,我在NSString上创建了一个类别,如下所示:

@implementation NSString (NSStringFromCPP)
+(NSString*)stringFromCppString:(std::string)cppString
{
    return [[NSString alloc] initWithCString:cppString.c_str() encoding:NSStringEncodingConversionAllowLossy];
}

-(std::string)cppString
{
    return std::string([self cStringUsingEncoding:NSStringEncodingConversionAllowLossy]);
}
@end

这允许在NSString和std::string之间双向进行相当容易的转换。不过,似乎必须有一种方法将std::string隐式转换为NSString。我知道Objective-C中没有构造函数,那么如何在不使用stringFromCppString 的情况下完成以下任务

-(void)something:(NSString*)someString
{
    NSLog(@"%@", someString);
}

-(void)activity
{
    std::string activityName = "Calculator";
    [self something:[NSString stringFromCppString:activityName]];
}

在大多数情况下,使用std::string的代码可以与使用NSString的代码分开。然而,会出现相当多的桥接,代码会因为到处都是stringFromCppString而变得分散注意力。

您应该将std::string const &作为Obj-C方法中参数的类型传递。

+(NSString*)stringFromCppString:(std::string const &)cppString;

另外,不要忘记,当编译为.mm时,您可以使用普通C++,所以您可能需要考虑像重载这样简单的东西。。。

std::string
cppString(char const *s)
{
  return s;
}
std::string const &
cppString(std::string const &s)
{
  return s;
}
std::string
cppString(NSString *s)
{
  return [self cStringUsingEncoding:DESIRED_ENCODING];
}

另一种方式。。。

NSString *
objcString(char const *s)
{
  return [NSString stringWithCString:s encoding:DESIRED_ENCODING];
}
NSString *
objcString(std::string const &s)
{
  return objcString(s.c_str());
}
NSString *
objcString(NSString *s)
{
  return s;
}

现在,只要你想要一个C++std::字符串,就只需调用cppString,只要你需要一个Obj-C NSString,就只需要调用objcString,你就不必真正关心"真实"字符串是什么…

或者,您可以使用转换运算符制作自己的字符串包装器。。。这也很简单。

然而,通常情况下,您可能希望您的C++是C++,而您的ObjC是ObjC,并使用.mm作为轻量级粘合剂。

Objective-C不提供任何在类型之间隐式转换的便利。事实上,它甚至没有强制转换对象的概念——因为所有对象都由指针引用,所以强制转换只是指针强制转换,不会更改底层数据。该语言提供的将对象转换为其他类型的唯一方法是调用对象上的方法。