Objective-C中连接NSStrings的快捷方式

在Objective-C中是否有(stringByAppendingString:)字符串连接的快捷方式,或者一般使用NSString的快捷方式?

例如,我想做:

NSString *myString = @"This";NSString *test = [myString stringByAppendingString:@" is just a test"];

更像是:

string myString = "This";string test = myString + " is just a test";
830183 次浏览

我能想到的两个答案……都没有仅仅拥有一个连接运算符那么令人愉快。

首先,使用NSMutableString,它有一个appendString方法,消除了对额外临时字符串的一些需求。

其次,使用NSArray通过componentsJoinedByString方法连接。

使c = [a stringByAppendingString: b]更短的唯一方法是在st点附近使用自动完成。+运算符是C的一部分,它不知道Objective-C对象。

一个选项:

[NSString stringWithFormat:@"%@/%@/%@", one, two, three];

另一种选择:

我猜你对多个追加(a+b+c+d)不满意,在这种情况下你可以这样做:

NSLog(@"%@", [Util append:one, @" ", two, nil]); // "one two"NSLog(@"%@", [Util append:three, @"/", two, @"/", one, nil]); // three/two/one

使用类似

+ (NSString *) append:(id) first, ...{NSString * result = @"";id eachArg;va_list alist;if(first){result = [result stringByAppendingString:first];va_start(alist, first);while (eachArg = va_arg(alist, id))result = [result stringByAppendingString:eachArg];va_end(alist);}return result;}
NSString *label1 = @"Process Name: ";NSString *label2 = @"Process Id: ";NSString *processName = [[NSProcessInfo processInfo] processName];NSString *processID = [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]];NSString *testConcat = [NSString stringWithFormat:@"%@ %@ %@ %@", label1, processName, label2, processID];

创建AppendString(AS)宏的快捷方式…

#define AS(A,B)    [(A) stringByAppendingString:(B)]
NSString *myString = @"This"; NSString *test = AS(myString,@" is just a test");

备注:

如果使用宏,当然只需使用可变参数,请参阅Ethan B的答案。

NSString *label1 = @"Process Name: ";NSString *label2 = @"Process Id: ";NSString *processName = [[NSProcessInfo processInfo] processName];NSString *processID = [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]];NSString *testConcat = [NSString stringWithFormat:@"%@ %@ %@ %@", label1, processName, label2, processID];

这样使用stringByAppendingString:

NSString *string1, *string2, *result;
string1 = @"This is ";string2 = @"my string.";
result = [result stringByAppendingString:string1];result = [result stringByAppendingString:string2];

result = [result stringByAppendingString:@"This is "];result = [result stringByAppendingString:@"my string."];

如果你有2个NSString文字,你也可以这样做:

NSString *joinedFromLiterals = @"ONE " @"MILLION " @"YEARS " @"DUNGEON!!!";

这对于连接#定义也很有用:

#define STRINGA @"Also, I don't know "#define STRINGB @"where food comes from."#define JOINED STRINGA STRINGB

好好享受。

这是为了更好的日志记录,并且仅基于dicius优秀的多参数方法。我定义了一个Logger类,并像这样调用它:

[Logger log: @"foobar ", @" asdads ", theString, nil];

几乎很好,除了必须以“nil”结束var args,但我想在Objective-C中没有办法解决这个问题。

Logger. h

@interface Logger : NSObject {}+ (void) log: (id) first, ...;@end

Logger. m

@implementation Logger
+ (void) log: (id) first, ...{// TODO: make efficient; handle arguments other than strings// thanks to @diciu http://stackoverflow.com/questions/510269/how-do-i-concatenate-strings-in-objective-cNSString * result = @"";id eachArg;va_list alist;if(first){result = [result stringByAppendingString:first];va_start(alist, first);while (eachArg = va_arg(alist, id)){result = [result stringByAppendingString:eachArg];}va_end(alist);}NSLog(@"%@", result);}
@end

为了只使用conat字符串,我在NSString上定义了一个类别,并添加了一个静态(+)连接方法,它看起来与上面的log方法完全相同,只是它返回字符串。它在NSString上,因为它是一个字符串方法,它是静态的,因为你想从1-N个字符串创建一个新字符串,而不是在附加的任何一个字符串上调用它。

创建一个方法:

- (NSString *)strCat: (NSString *)one: (NSString *)two{NSString *myString;myString = [NSString stringWithFormat:@"%@%@", one , two];return myString;}

然后,在任何需要它的函数中,将字符串或文本字段或任何内容设置为该函数的返回值。

或者,要创建快捷方式,请将NSString转换为C++字符串并在那里使用“+”。

好吧,因为冒号是一种特殊的符号,但是方法签名的一部分,所以可以用类别extedNSString来添加这种非惯用风格的字符串连接:

[@"This " : @"feels " : @"almost like " : @"concatenation with operators"];

您可以定义尽可能多的冒号分隔的参数,因为你觉得有用…;-)

为了更好的度量,我还添加了带有变量参数的concat:,该参数采用nil终止的字符串列表。

//  NSString+Concatenation.h
#import <Foundation/Foundation.h>
@interface NSString (Concatenation)
- (NSString *):(NSString *)a;- (NSString *):(NSString *)a :(NSString *)b;- (NSString *):(NSString *)a :(NSString *)b :(NSString *)c;- (NSString *):(NSString *)a :(NSString *)b :(NSString *)c :(NSString *)d;
- (NSString *)concat:(NSString *)strings, ...;
@end
//  NSString+Concatenation.m
#import "NSString+Concatenation.h"
@implementation NSString (Concatenation)
- (NSString *):(NSString *)a { return [self stringByAppendingString:a];}- (NSString *):(NSString *)a :(NSString *)b { return [[self:a]:b];}- (NSString *):(NSString *)a :(NSString *)b :(NSString *)c{ return [[[self:a]:b]:c]; }- (NSString *):(NSString *)a :(NSString *)b :(NSString *)c :(NSString *)d{ return [[[[self:a]:b]:c]:d];}
- (NSString *)concat:(NSString *)strings, ...{va_list args;va_start(args, strings);
NSString *s;NSString *con = [self stringByAppendingString:strings];
while((s = va_arg(args, NSString *)))con = [con stringByAppendingString:s];
va_end(args);return con;}@end
//  NSString+ConcatenationTest.h
#import <SenTestingKit/SenTestingKit.h>#import "NSString+Concatenation.h"
@interface NSString_ConcatenationTest : SenTestCase
@end
//  NSString+ConcatenationTest.m
#import "NSString+ConcatenationTest.h"
@implementation NSString_ConcatenationTest
- (void)testSimpleConcatenation{STAssertEqualObjects([@"a":@"b"], @"ab", nil);STAssertEqualObjects([@"a":@"b":@"c"], @"abc", nil);STAssertEqualObjects([@"a":@"b":@"c":@"d"], @"abcd", nil);STAssertEqualObjects([@"a":@"b":@"c":@"d":@"e"], @"abcde", nil);STAssertEqualObjects([@"this " : @"is " : @"string " : @"concatenation"],@"this is string concatenation", nil);}
- (void)testVarArgConcatenation{NSString *concatenation = [@"a" concat:@"b", nil];STAssertEqualObjects(concatenation, @"ab", nil);
concatenation = [concatenation concat:@"c", @"d", concatenation, nil];STAssertEqualObjects(concatenation, @"abcdab", nil);}

在构建Web服务请求时,我发现执行以下操作非常容易,并使连接在Xcode中具有可读性:

NSString* postBody = {@"<?xml version=\"1.0\" encoding=\"utf-8\"?>"@"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"@" <soap:Body>"@"  <WebServiceMethod xmlns=\"\">"@"   <parameter>test</parameter>"@"  </WebServiceMethod>"@" </soap:Body>"@"</soap:Envelope>"};

如何缩短stringByAppendingString并使用#定义

#define and stringByAppendingString

因此,您将使用:

NSString* myString = [@"Hello " and @"world"];

问题是它只适用于两个字符串,您需要包装额外的括号以获取更多附加:

NSString* myString = [[@"Hello" and: @" world"] and: @" again"];

我一直回到这篇文章,最后总是对答案进行排序,找到这个简单的解决方案,可以根据需要使用尽可能多的变量:

[NSString stringWithFormat:@"%@/%@/%@", three, two, one];

例如:

NSString *urlForHttpGet = [NSString stringWithFormat:@"http://example.com/login/username/%@/userid/%i", userName, userId];

这里有一个简单的方法,使用新的数组文字语法:

NSString * s = [@[@"one ", @"two ", @"three"] componentsJoinedByString:@""];^^^^^^^ create array ^^^^^^^^^^^^ concatenate ^^^^^

试试stringWith Format:

NSString *myString = [NSString stringWithFormat:@"%@ %@ %@ %d", "The", "Answer", "Is", 42];

在处理字符串时,我经常发现制作源文件ObjC++更容易,然后我可以使用问题中显示的第二种方法连接std::字符串。

std::string stdstr = [nsstr UTF8String];
//easier to read and more portable string manipulation goes here...
NSString* nsstr = [NSString stringWithUTF8String:stdstr.c_str()];
listOfCatalogIDs =[@[@"id[]=",listOfCatalogIDs] componentsJoinedByString:@""];

您可以使用NSArray作为

NSString *string1=@"This"
NSString *string2=@"is just"
NSString *string3=@"a test"
NSArray *myStrings = [[NSArray alloc] initWithObjects:string1, string2, string3,nil];
NSString *fullLengthString = [myStrings componentsJoinedByString:@" "];

您可以使用

NSString *imageFullName=[NSString stringWithFormat:@"%@ %@ %@.", string1,string2,string3];
NSString *result=[NSString stringWithFormat:@"%@ %@", @"Hello", @"World"];

我的首选方法是:

NSString *firstString = @"foo";NSString *secondString = @"bar";NSString *thirdString = @"baz";
NSString *joinedString = [@[firstString, secondString, thirdString] join];

您可以通过使用类别将连接方法添加到NSArray来实现它:

#import "NSArray+Join.h"@implementation NSArray (Join)-(NSString *)join{return [self componentsJoinedByString:@""];}@end

@[]这是NSArray的简短定义,我认为这是连接字符串的最快方法。

如果您不想使用类别,请直接使用componentsJoinedByString:方法:

NSString *joinedString = [@[firstString, secondString, thirdString] componentsJoinedByString:@""];

我试过这个代码。它对我有用。

NSMutableString * myString=[[NSMutableString alloc]init];myString=[myString stringByAppendingString:@"first value"];myString=[myString stringByAppendingString:@"second string"];

宏:

// stringConcat(...)//     A shortcut for concatenating strings (or objects' string representations).//     Input: Any number of non-nil NSObjects.//     Output: All arguments concatenated together into a single NSString.
#define stringConcat(...) \[@[__VA_ARGS__] componentsJoinedByString:@""]

测试用例:

- (void)testStringConcat {NSString *actual;
actual = stringConcat(); //might not make sense, but it's still a valid expression.STAssertEqualObjects(@"", actual, @"stringConcat");
actual = stringConcat(@"A");STAssertEqualObjects(@"A", actual, @"stringConcat");
actual = stringConcat(@"A", @"B");STAssertEqualObjects(@"AB", actual, @"stringConcat");
actual = stringConcat(@"A", @"B", @"C");STAssertEqualObjects(@"ABC", actual, @"stringConcat");
// works on all NSObjects (not just strings):actual = stringConcat(@1, @" ", @2, @" ", @3);STAssertEqualObjects(@"1 2 3", actual, @"stringConcat");}

备用宏:(如果您想强制执行最少数量的参数)

// stringConcat(...)//     A shortcut for concatenating strings (or objects' string representations).//     Input: Two or more non-nil NSObjects.//     Output: All arguments concatenated together into a single NSString.
#define stringConcat(str1, str2, ...) \[@[ str1, str2, ##__VA_ARGS__] componentsJoinedByString:@""];
NSString *myString = @"This";NSString *test = [myString stringByAppendingString:@" is just a test"];

在使用ObjectiveC几年之后,我认为这是使用ObjectiveC实现您想要实现的目标的最佳方式。

开始在Xcode应用程序中键入“N”,它会自动完成为“NSString”。键入“str”并自动完成“stringByAppendingString”。所以击键非常有限。

一旦你掌握了敲击“@”键和选项卡的诀窍,编写可读代码的过程就不再是问题了。这只是一个适应的问题。

lldb窗格中尝试以下操作

[NSString stringWithFormat:@"%@/%@/%@", three, two, one];

哪些错误。

而是使用alloc和initWithFormat方法:

[[NSString alloc] initWithFormat:@"%@/%@/%@", @"three", @"two", @"one"];
NSNumber *lat = [NSNumber numberWithDouble:destinationMapView.camera.target.latitude];NSNumber *lon = [NSNumber numberWithDouble:destinationMapView.camera.target.longitude];NSString *DesconCatenated = [NSString stringWithFormat:@"%@|%@",lat,lon];

当我测试时,这些格式中的任何一种都可以在XCode7中工作:

NSString *sTest1 = {@"This" " and that" " and one more"};NSString *sTest2 = {@"This"" and that"" and one more"};
NSLog(@"\n%@\n\n%@",sTest1,sTest2);

出于某种原因,您只需要在混音的第一个字符串上使用@操作符。

但是,它不适用于变量插入。为此,您可以使用这个极其简单的解决方案,但在“cat”而不是“and”上使用宏除外。

让我们假设你不知道有多少弦。

NSMutableArray *arrForStrings = [[NSMutableArray alloc] init];for (int i=0; i<[allMyStrings count]; i++) {NSString *str = [allMyStrings objectAtIndex:i];[arrForStrings addObject:str];}NSString *readyString = [[arrForStrings mutableCopy] componentsJoinedByString:@", "];

对于所有在UI测试中需要此功能的ObjectiveC爱好者:

-(void) clearTextField:(XCUIElement*) textField{
NSString* currentInput = (NSString*) textField.value;NSMutableString* deleteString = [NSMutableString new];
for(int i = 0; i < currentInput.length; ++i) {[deleteString appendString: [NSString stringWithFormat:@"%c", 8]];}[textField typeText:deleteString];}

受ChrisNSMutableString想法的启发,我制作了一个完美的宏imho。它支持无异常插入nil元素。

#import <libextobjc/metamacros.h>
#define STR_CONCAT(...) \({ \__auto_type str__ = [NSMutableString string]; \metamacro_foreach_cxt(never_use_immediately_str_concatify_,, str__, __VA_ARGS__) \(NSString *)str__.copy; \})
#define never_use_immediately_str_concatify_(INDEX, CONTEXT, VAR) \[CONTEXT appendString:VAR ?: @""];

示例:

STR_CONCAT(@"button_bg_", @(count).stringValue, @".png");// button_bg_2.png

如果您愿意,您可以使用id类型作为参数,使用[VAR description]而不是NSString