Objective-C中用于连接nsstring的快捷方式

Shortcuts in Objective-C to concatenate NSStrings

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

例如,我想:

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 *) 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;
}


我能想到两个答案…这两种方法都不如使用串联运算符那么简单。

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

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


如果有两个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来扩展NSString,以添加这种非惯用的字符串连接样式:

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

您可以定义尽可能多的冒号分隔参数…;-)

为了更好的度量,我还添加了带有可变参数的concat:,这些参数采用了以nil结尾的字符串列表。

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"。所以击键是非常有限的。

一旦你掌握了按"@"键和选择键的窍门,写可读代码的过程就不再是问题了。这只是一个适应的问题。


使c = [a stringByAppendingString: b]变短的唯一方法是在st点附近使用自动完成。+操作符是c的一部分,它不了解objective-c对象。


1
NSString *result=[NSString stringWithFormat:@"%@ %@", @"Hello", @"World"];

缩短stringByAppendingString并使用a定义:

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];

lldb窗格中尝试以下内容

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

哪些错误。

相反,使用alloc和initWithFormat方法:

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
[Logger log: @"foobar", @" asdads", theString, nil];

几乎很好,除了必须以"nil"结束var参数,但我认为在objective-c中没有办法解决这个问题。

记录器

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

记录器

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

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

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

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"