Shortcuts in Objective-C to concatenate NSStrings
在Objective-C中是否有(
例如,我想:
1 2 | NSString *myString = @"This"; NSString *test = [myString stringByAppendingString:@" is just a test"]; |
更像是:
1 2 | string myString ="This"; string test = myString +" is just a test"; |
一种选择:
1 | [NSString stringWithFormat:@"%@/%@/%@", one, two, three]; |
另一种选择:
我猜你对多个附件(A+B+C+D)不满意,在这种情况下,你可以这样做:
1 2 | NSLog(@"%@", [Util append:one, @"", two, nil]); //"one two" NSLog(@"%@", [Util append:three, @"/", two, @"/", one, nil]); // three/two/one |
使用类似
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
我能想到两个答案…这两种方法都不如使用串联运算符那么简单。
首先,使用一个
其次,使用
如果有两个nsstring文本,也可以这样做:
1 | NSString *joinedFromLiterals = @"ONE" @"MILLION" @"YEARS" @"DUNGEON!!!"; |
这对于连接也很有用定义:
1 2 3 | #define STRINGA @"Also, I don't know" #define STRINGB @"where food comes from." #define JOINED STRINGA STRINGB |
享受。
我一直回到这篇文章,最后总是对答案进行排序,以找到这个简单的解决方案,它可以根据需要使用任意多的变量:
1 | [NSString stringWithFormat:@"%@/%@/%@", three, two, one]; |
例如:
1 | NSString *urlForHttpGet = [NSString stringWithFormat:@"http://example.com/login/username/%@/userid/%i", userName, userId]; |
好吧,因为冒号是一种特殊的符号,但它是方法签名的一部分,所以可以用category来扩展
1 | [@"This" : @"feels" : @"almost like" : @"concatenation with operators"]; |
您可以定义尽可能多的冒号分隔参数…;-)
为了更好的度量,我还添加了带有可变参数的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | // 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); } |
创建方法:
1 2 3 4 5 6 | - (NSString *)strCat: (NSString *)one: (NSString *)two { NSString *myString; myString = [NSString stringWithFormat:@"%@%@", one , two]; return myString; } |
然后,在需要它的任何函数中,将字符串或文本字段或任何内容设置为此函数的返回值。
或者,要做快捷方式,将NString转换成C++字符串并使用"+"。
用这种方式:
1 2 3 4 5 6 7 | NSString *string1, *string2, *result; string1 = @"This is"; string2 = @"my string."; result = [result stringByAppendingString:string1]; result = [result stringByAppendingString:string2]; |
或
1 2 | result = [result stringByAppendingString:@"This is"]; result = [result stringByAppendingString:@"my string."]; |
宏:
1 2 3 4 5 6 7 | // 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:@""] |
测试用例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | - (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"); } |
备用宏:(如果要强制使用最少数量的参数)
1 2 3 4 5 6 7 | // 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:@""]; |
在构建Web服务请求时,我发现这样做非常容易,并且可以在Xcode中读取连接:
1 2 3 4 5 6 7 8 9 10 | 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>" }; |
通过创建AppendString(as)宏的快捷方式…
1 2 3 4 | #define AS(A,B) [(A) stringByAppendingString:(B)] NSString *myString = @"This"; NSString *test = AS(myString,@" is just a test"); |
注:
如果使用宏,当然只需使用变量参数,请参见Ethanb的答案。
1 2 3 4 5 | 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]; |
下面是一个简单的方法,使用新的数组文字语法:
1 2 3 | NSString * s = [@[@"one", @"two", @"three"] componentsJoinedByString:@""]; ^^^^^^^ create array ^^^^^ ^^^^^^^ concatenate ^^^^^ |
1 2 | NSString *myString = @"This"; NSString *test = [myString stringByAppendingString:@" is just a test"]; |
几年后,我认为这是与目标C合作的最佳方式,以实现你正在努力实现的目标。
开始在Xcode应用程序中输入"n",它会自动完成"nsstring"。输入"str"并自动完成"stringByAppendingString"。所以击键是非常有限的。
一旦你掌握了按"@"键和选择键的窍门,写可读代码的过程就不再是问题了。这只是一个适应的问题。
使
1 | NSString *result=[NSString stringWithFormat:@"%@ %@", @"Hello", @"World"]; |
缩短
1 | #define and stringByAppendingString |
因此,您将使用:
1 | NSString* myString = [@"Hello" and @"world"]; |
问题是它只适用于两个字符串,您需要为更多的附加部分包装额外的括号:
1 | NSString* myString = [[@"Hello" and: @" world"] and: @" again"]; |
1 2 3 4 5 | 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]; |
在
1 | [NSString stringWithFormat:@"%@/%@/%@", three, two, one]; |
哪些错误。
相反,使用alloc和
1 | [[NSString alloc] initWithFormat:@"%@/%@/%@", @"three", @"two", @"one"]; |
我试过这个密码。这对我有用。
1 2 3 | NSMutableString * myString=[[NSMutableString alloc]init]; myString=[myString stringByAppendingString:@"first value"]; myString=[myString stringByAppendingString:@"second string"]; |
1 2 3 | NSNumber *lat = [NSNumber numberWithDouble:destinationMapView.camera.target.latitude]; NSNumber *lon = [NSNumber numberWithDouble:destinationMapView.camera.target.longitude]; NSString *DesconCatenated = [NSString stringWithFormat:@"%@|%@",lat,lon]; |
这是为了更好地记录,并且只记录-基于Dicius优秀的多参数方法。我定义了一个logger类,并这样调用它:
1 |
几乎很好,除了必须以"nil"结束var参数,但我认为在objective-c中没有办法解决这个问题。
记录器
1 2 3 4 |
记录器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | @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-c 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); } NSLog(@"%@", result); } @end |
为了只使用concat字符串,我将在nsstring上定义一个类别,并向它添加一个静态的(+)concatenate方法,该方法与上面的log方法完全相同,只是它返回字符串。它在nsstring上,因为它是一个字符串方法,它是静态的,因为您希望从1-n个字符串创建一个新的字符串,而不是在附加的任何一个字符串上调用它。
我的首选方法是:
1 2 3 4 5 | NSString *firstString = @"foo"; NSString *secondString = @"bar"; NSString *thirdString = @"baz"; NSString *joinedString = [@[firstString, secondString, thirdString] join]; |
您可以通过将join方法添加到具有类别的nsarray来实现它:
1 2 3 4 5 6 7 | #import"NSArray+Join.h" @implementation NSArray (Join) -(NSString *)join { return [self componentsJoinedByString:@""]; } @end |
如果不想使用类别,直接使用
1 | NSString *joinedString = [@[firstString, secondString, thirdString] componentsJoinedByString:@""]; |
你可以使用nsarray作为
1 2 3 4 5 6 7 8 9 | NSString *string1=@"This" NSString *string2=@"is just" NSString *string3=@"a test" NSArray *myStrings = [[NSArray alloc] initWithObjects:string1, string2, string3,nil]; NSString *fullLengthString = [myStrings componentsJoinedByString:@""]; |
或
你可以使用
1 | NSString *imageFullName=[NSString stringWithFormat:@"%@ %@ %@.", string1,string2,string3]; |
尝试字符串格式:
1 | NSString *myString = [NSString stringWithFormat:@"%@ %@ %@ %d","The","Answer","Is", 42]; |
当经常处理字符串时,我发现使源文件objc++更容易,然后我可以使用问题中所示的第二个方法连接std::strings。
1 2 3 4 5 | std::string stdstr = [nsstr UTF8String]; //easier to read and more portable string manipulation goes here... NSString* nsstr = [NSString stringWithUTF8String:stdstr.c_str()]; |
当我测试时,这些格式中的任何一种都在xcode7中工作:
1 2 3 4 5 6 7 8 9 10 11 | NSString *sTest1 = {@"This"" and that"" and one more"}; NSString *sTest2 = { @"This" " and that" " and one more" }; NSLog(@" %@ %@",sTest1,sTest2); |
出于某种原因,您只需要在组合的第一个字符串上使用@operator字符。
但是,它不适用于变量插入。为此,您可以使用这个非常简单的解决方案,除了在"cat"上使用宏而不是"and"。
对于在UI测试中需要此功能的所有目标C爱好者:
1 2 3 4 5 6 7 8 9 10 | -(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]; } |
1 | listOfCatalogIDs =[@[@"id[]=",listOfCatalogIDs] componentsJoinedByString:@""]; |
让我们想象一下,你不知道有多少弦。
1 2 3 4 5 6 | 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:@","]; |
在Swift
1 2 3 4 5 | let str1 ="This" let str2 ="is just a test" var appendStr1 ="\(str1) \(str2)" // appendStr1 would be"This is just a test" var appendStr2 = str1 + str2 // // appendStr2 would be"This is just a test" |
此外,您还可以使用
1 2 | var str3 ="Some String" str3 += str2 // str3 would be"Some String is just a test" |