1149

Are there any shortcuts to (stringByAppendingString:) string concatenation in Objective-C, or shortcuts for working with NSString in general?

For example, I'd like to make:

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

something more like:

string myString = "This";
string test = myString + " is just a test";
Forge
  • 5,854
  • 6
  • 41
  • 58
typeoneerror
  • 51,338
  • 32
  • 124
  • 213
  • Shortest *hack* in obj-c syntax would be `[@"This" : @" works" : @" OK"];` when you extend the NSString with your own category. See answer below. – Palimondo Mar 19 '12 at 09:23
  • @ranReloaded ever heard of ARC? – cheesus Jul 20 '12 at 11:07
  • @cheeesus Yes. Still. ARC is not GC, and retain cycles are possible. You need to be aware, if not of retain counts, at least of object ownership (graph). – Nicolas Miari Jul 20 '12 at 11:28
  • 4
    I'd just like to propose '@+' as a concatenation operator. I'll expect this in the next update to Objective-C, kthxbai – powerj1984 Jan 15 '13 at 20:15
  • 1
    Forget the @ symbol, just make Obj-C support operator overloading like C++ does! That's what I want. – devios1 Mar 13 '13 at 20:24
  • 1
    @Jordão Wow that's cool... using C++ on top of Objective-C for operator overloading. Now *that* warrants some looking into. – devios1 Mar 13 '13 at 20:50
  • 46
    @NicolasMiari This is not the only feature that Objective-C lacks. There are dozens of others. Quoting from the [link](http://luminaryapps.com/blog/sweetened-cocoa-the-string-class/) Jordão posted: "Objective-C is, to be blunt, a primitive language. Compare it to any modern language and you quickly find it lacking." I agree. Objective-C (early 1980s) is C (early 1970s) with the addition of a very simple and not very type-safe kind of OOP. It's ok, but compared with Java or C#, it feels very old-fashioned. – jcsahnwaldt Reinstate Monica Aug 15 '13 at 09:13
  • 1
    ...it all boils down to what you want to do. C# and Java might be full of "modern features", but I personally would never code computer graphics in an interpreted language when there's C or Obj-C available. – Nicolas Miari Aug 15 '13 at 09:23
  • 6
    @NicolasMiari: Interpreted language? C# and Java are compiled languages. Compiled to bytecode, which is then compiled again to machine code. – Joren Sep 16 '13 at 11:20
  • 1
    You mean "[...]Which is then compiled again to machine code, at runtime, just in time". – Nicolas Miari Sep 16 '13 at 11:45
  • You expectation of a + operator for strings in Objective-C belies a fundamental misunderstanding of Objective-C's design & legacy. – orj Feb 19 '14 at 23:45
  • 3
    Things are changed now : Swift (apple new language) is more straightforward – Pradeep Jun 11 '14 at 19:45
  • @NicolasMiari How is allowing us to "add" strings dirty? It would do the same thing but with less typing. You don't have to worry about it bringing us down to slow junk like Java. – sudo Jul 09 '14 at 16:50
  • 1
    Because it may seem more straightforward and intuitive, but in exchange it sacrifices the kind of fine-grained control you have with e.g. `printf()`'s format specifiers (%f, %.2f, %06d etc.) Instead, you have to use `someIntegerVar.ToString()`. – Nicolas Miari Jul 18 '14 at 01:04
  • Regarding modern features and feeling "dated": Objective-C introduced Automatic Reference Counting a few years ago, which is the best thing since sliced bread; literally "The Best Of Both Worlds". Meanwhile, everyone else still is stuck with garbage collectors. People developing games with e.g. Unity3d have to jump through hoops and recycle objects in "pools" to avoid the performance hit when the undeterministic GC kicks in. – Nicolas Miari Jul 18 '14 at 01:09
  • 6
    Regarding "type safety", I think it's a problem of style. For someone coming from C#/C++, having heterogeneous arrays of objects of any type might seem odd, but for someone accustomed to Objective-C/Cocoa, it's a form of dynamism and freedom; it is an advantage provided you know what you are doing. Like pretty much everything about C that younger programmers bash these days... – Nicolas Miari Jul 18 '14 at 01:11
  • @Braiam: This question most definitely has to do with those tags you removed; its _subject_ is `NSString`! And the Cocoa and Cocoa Touch frameworks are the source of the `NSString` class. – jscs Nov 05 '14 at 09:08
  • 1
    If you're doing low-level work, use C, assembly, or (if you have a background in hardware) Verilog (not VHDL, because VHDL is terrible). If you're doing high level work, use python or haskell. If you're doing low-level work, but want the power of a higher level language, use C++. Don't like garbage collection? C++ has smart pointers. The only reason anyone would ever write anything in Objective C is to target Apple products, and frankly that's not a good reason. Objective C combines the worst of both worlds; the error-proneness of C with the unfathomable prolixity of Java. – Parthian Shot Apr 22 '15 at 04:28
  • Just in case anyone is curious, in Swift you *are* able to use `let name = "Long" + "face"` – William Entriken Jan 21 '16 at 14:22

30 Answers30

1151

An option:

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

Another option:

I'm guessing you're not happy with multiple appends (a+b+c+d), in which case you could do:

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

using something like

+ (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;
}
Jimmy Schementi
  • 1,211
  • 8
  • 16
diciu
  • 28,395
  • 4
  • 48
  • 68
  • 8
    @pablasso Agreed. The Util method is pretty ugly. If you wanted such a thing, it should be done as a NSString category with a name like +stringByAppendingStrings:. Even a straight-up function with a name like NSStringForAppendedStrings(...) would be better than a static method in a class like Util (anything with "Util" in the name is likely poorly factored). The function is also better implemented with an NSMutableString and -appendString to avoid creating an unbounded set of temporary autoreleased NSStrings. – Rob Napier Feb 16 '10 at 14:34
  • 1
    With large strings this can waste memory. Recommended is something more like StringBuilder in real programming languages. Then you could just figure out how much memory is needed before you actually start appending. The above approach could be refactored to do this. However, it would be better to make a StringBuilder object as this would save the user of it from having to keep track of a list of all the strings they need combined. – George Oct 12 '11 at 23:57
  • how do you import Util? this IDE is frustrating (no suggested "import something.Util" like on eclipse, and I find no mention of "Util" anywhere. Is this a class I'm supposed to code myself? – Gubatron Sep 19 '14 at 23:48
  • stringWithFormat is not only very elegant, it is also much more powerful. You use it with @"%@%@" to concatenate two strings, @"%@%@%@" to concatenate three strings, but you can put any extra characters inside, print numbers, reorder parameters if you like and so on. The format string can be localised, making it ten times more powerful. String concatenation is for beginners. – gnasher729 Apr 28 '15 at 18:37
628

Two answers I can think of... neither is particularly as pleasant as just having a concatenation operator.

First, use an NSMutableString, which has an appendString method, removing some of the need for extra temp strings.

Second, use an NSArray to concatenate via the componentsJoinedByString method.

Michael Fredrickson
  • 34,884
  • 5
  • 81
  • 104
Chris Blackwell
  • 9,059
  • 1
  • 22
  • 26
  • 34
    Although the other option has many upvotes, I think this is the best answer if you don't know all your strings upon construction. Every time you append a string, you're creating a lot of overhead. Using a mutable string removes that problem. – Eli Dec 22 '09 at 01:25
  • 22
    +1 Agree w @Eli. These are generally the best solutions. NSArray -componentsJoinedByString can be done in a single line pretty well: string = [[NSArray arrayWithObjects:@"This", "Is", "A", "Test", nil] componentsJoinedByString:@" "]; – Rob Napier Feb 16 '10 at 14:37
  • 5
    +1 for this answer. `[NSMutableString appendString]` is more memory friendly than `[NSString stringByAppendingStrings]`. – Pierre-David Belanger Sep 27 '11 at 14:22
  • 2
    @RobNapier:Now with the new array literal syntax, it is even better. – Amogh Talpallikar Jul 02 '13 at 07:12
  • 29
    The `[NSString stringWithFormat:@"%@/%@/%@", three, two, one];` technique seems the most elegant. It should be the selected answer. – ekillaby Feb 21 '14 at 19:39
  • Just to be clear. editable array = `NSMutableArray`, editable dictionary = `NSMutableDictionary`, editable string = `NSMutableString`. When using a NSString you will not be able to change a portion of the value. – Ratata Tata May 07 '14 at 18:50
  • @ekillaby Note, however, that in that case, `three` would come first. – ReinstateMonica3167040 Feb 03 '20 at 13:23
154

If you have 2 NSString literals, you can also just do this:

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

That's also useful for joining #defines:

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

Enjoy.

Johannes Fahrenkrug
  • 38,500
  • 17
  • 113
  • 155
  • 13
    @CristiBăluță :) But this works only with _literals_ not with dynamically created NSString instances. – Johannes Fahrenkrug Nov 23 '12 at 19:23
  • 10
    You actually don't need the `@`s on the strings after the first. `@"I" " really" " enjoy"...` – Kevin May 11 '13 at 17:49
  • You should probably want to put STRINGA and STRINGB within parenthesis, otherwise you might get weird results when the macro is resolved. #define JOINED (STRINGA STRINGB) – digory doo Jul 30 '13 at 17:04
  • @JohannesFahrenkrug Then why this `NSString* const SQL_CREATE_TABLE_str = @"CREATE TABLE IF NOT EXISTS " TABLE_NAME @" (...);";` doesn't work? I'm having `Expected '@' in program` error :( – Vagif Jun 01 '17 at 19:56
  • @Vagif how is `TABLE_NAME` defined? – Johannes Fahrenkrug Jun 06 '17 at 15:56
  • @JohannesFahrenkrug I tried both ways `NSString* const EVENT_TABLE_NAME = @"events";` and `#define EVENT_TABLE_NAME @"events";` neither worked. – Vagif Jun 06 '17 at 21:09
  • Just so you know, you shouldn't have the `;` in the `#define` – `#define` doesn't care about it, so it'll be expanded at the end. This will mess up your concatenation. – SilverWolf Oct 11 '17 at 14:28
80

I keep returning to this post and always end up sorting through the answers to find this simple solution that works with as many variables as needed:

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

For example:

NSString *urlForHttpGet = [NSString stringWithFormat:@"http://example.com/login/username/%@/userid/%i", userName, userId];
jdphenix
  • 13,519
  • 3
  • 37
  • 68
Kyle Clegg
  • 36,212
  • 26
  • 127
  • 138
52

Create a method:

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

Then, in whatever function you need it in, set your string or text field or whatever to the return value of this function.

Or, to make a shortcut, convert the NSString into a C++ string and use the '+' there.

Pang
  • 8,605
  • 144
  • 77
  • 113
Sidd Menon
  • 797
  • 6
  • 17
45

Well, as colon is kind of special symbol, but is part of method signature, it is possible to exted the NSString with category to add this non-idiomatic style of string concatenation:

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

You can define as many colon separated arguments as you find useful... ;-)

For a good measure, I've also added concat: with variable arguments that takes nil terminated list of strings.

//  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);
}
Palimondo
  • 6,961
  • 4
  • 37
  • 54
  • 20
    I downvoted this a year ago because it's not a very good answer. To cope with concatenating a large number of strings, Palimondo's implementation requires either implementing a large number of very similar looking methods, or calling the methods several times, resulting in a large chunk of code that essentially just concatenates strings. Using this approach, you don't get any benefit over a simple `stringWithFormat:`. Not to mention the lack of named parameters which is not only non-standard but also confusing. – FreeAsInBeer Mar 26 '13 at 12:57
  • 2
    The original asker mentioned `stringByAppendingString`, and he never said anything about using more than two arguments. I like this answer better than the accepted one. It's pretty clever. – sudo Jul 09 '14 at 17:00
37

Use stringByAppendingString: this way:

NSString *string1, *string2, *result;

string1 = @"This is ";
string2 = @"my string.";

result = [result stringByAppendingString:string1];
result = [result stringByAppendingString:string2];

OR

result = [result stringByAppendingString:@"This is "];
result = [result stringByAppendingString:@"my string."];
Taimur Ajmal
  • 2,764
  • 6
  • 36
  • 55
31

Macro:

// 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:@""]

Test Cases:

- (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");
}

Alternate macro: (if you wanted to enforce a minimum number of arguments)

// 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:@""];
EthanB
  • 4,006
  • 1
  • 24
  • 45
  • 2
    Haven't checked this question in a while, but I'm leaning towards accepting this as the right answer after all these years! – typeoneerror Jan 29 '16 at 06:25
  • 1
    This also arguably has better behaviour than `-[NSString stringByAppendingString:]` for this use case — with the former you'll get an exception if the argument is `nil` but not if the receiver is. So it's conceivably 50% odds on a mistake in your string feeder failing silently and 50% on an exception. With `stringConcat` you're guaranteed an exception on any `nil`, anywhere in the list. Which at least is more predictable. – Tommy Sep 19 '16 at 20:46
27

Shortcut by creating AppendString (AS) macro ...

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

Note:

If using a macro, of course just do it with variadic arguments, see EthanB's answer.

etarion
  • 15,781
  • 4
  • 40
  • 64
  • Cool! I still think the Util above is a much more elegant solution; you can append only one string with this macro, right? – typeoneerror Jul 18 '09 at 13:02
  • 1
    True, the AS macro above does one append per line of code. If multiple appends are a common need, then more macros can be created. For example, a macro to append two strings:
    #define A2S(A,B,C)    [[(A) stringByAppendingString:(B)] stringByAppendingString:(C)]
    
    –  Jul 18 '09 at 23:54
  • 2
    Or, simply shorten the typing required with a macro like "#define AS stringByAppendingString", then just use "AS" where your would normally type "stringByAppendingString", and enjoy multiple appends per line of code. –  Jul 19 '09 at 00:02
  • 15
    The problem with these macros is that they undermine one of the major goals of Objective-C, which is readability. It's extremely unclear what "AS" does. Saving a few keystrokes (most of which are handled with autocompletion) at the expense of readability is seldom a good trade-off. There are exceptions (the @"" syntax is much more readable than having to use +stringWithUTF8String: every time), but the goal should still be readability rather than simply brevity. You write once, but you debug forever. – Rob Napier Feb 16 '10 at 14:42
  • Hi Rob - I can't agree with you in this. Sure, "AS" is a bad name. It should be named perhaps "CAT". – Fattie Dec 18 '15 at 02:49
27

When building requests for web services, I find doing something like the following is very easy and makes concatenation readable in 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>"
};
FreeAsInBeer
  • 12,837
  • 5
  • 46
  • 79
  • For an objective-c noob can you explain what this syntax is doing? Is this creating an array of strings and joining them somewhow? A reference to any docs would be cool too. – Norman H May 25 '12 at 13:05
  • 2
    @NormanH: This is actually part of the C language. After a little digging, I was able to find [this](http://msdn.microsoft.com/en-us/library/bxss3ska(v=vs.80).aspx). It states under the "String concatenation" phase: All adjacent string and wide-string literals are concatenated. For example, "String " "concatenation" becomes "String concatenation". – FreeAsInBeer May 25 '12 at 18:58
13
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];
Stephen Darlington
  • 49,617
  • 11
  • 101
  • 147
coder284
  • 831
  • 12
  • 33
11

Here's a simple way, using the new array literal syntax:

NSString * s = [@[@"one ", @"two ", @"three"] componentsJoinedByString:@""];
                  ^^^^^^^ create array ^^^^^
                                               ^^^^^^^ concatenate ^^^^^
justin
  • 101,751
  • 13
  • 172
  • 222
9
NSString *myString = @"This";
NSString *test = [myString stringByAppendingString:@" is just a test"];

After a couple of years now with Objective C I think this is the best way to work with Objective C to achieve what you are trying to achieve.

Start keying in "N" in your Xcode application and it autocompletes to "NSString". key in "str" and it autocompletes to "stringByAppendingString". So the keystrokes are quite limited.

Once you get the hang of hitting the "@" key and tabbing the process of writing readable code no longer becomes a problem. It is just a matter of adapting.

Ian Clay
  • 582
  • 1
  • 8
  • 18
8

How about shortening stringByAppendingString and use a #define:

#define and stringByAppendingString

Thus you would use:

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

Problem is that it only works for two strings, you're required to wrap additional brackets for more appends:

NSString* myString = [[@"Hello" and: @" world"] and: @" again"];
Sunday Ironfoot
  • 12,268
  • 13
  • 71
  • 89
  • XCode7 won't let you use this option anymore -- says "and" is a reserved word. However, you can use "cat" instead, for conCATenation. I did and your solution works perfectly and is extremely simple. – Volomike Jan 28 '16 at 20:10
8
NSString *result=[NSString stringWithFormat:@"%@ %@", @"Hello", @"World"];
Pete
  • 51,385
  • 23
  • 99
  • 140
Gobi M
  • 3,035
  • 4
  • 29
  • 44
8

The only way to make c = [a stringByAppendingString: b] any shorter is to use autocomplete at around the st point. The + operator is part of C, which doesn't know about Objective-C objects.

7
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];
aleemb
  • 28,346
  • 17
  • 92
  • 111
6

I tried this code. it's worked for me.

NSMutableString * myString=[[NSMutableString alloc]init];
myString=[myString stringByAppendingString:@"first value"];
myString=[myString stringByAppendingString:@"second string"];
Erhan Demirci
  • 3,923
  • 3
  • 32
  • 42
  • 2
    This is the worst abuse of an NSMutableString ever. The whole point of NSMutableString is that you don't need methods creating autoreleased strings but can modify the string itself. – gnasher729 Apr 28 '15 at 18:41
  • Agree. At least use [`appendString:`](https://developer.apple.com/documentation/foundation/nsmutablestring/1417883-appendstring?language=objc) if you're using a `NSMutableString`. – ReinstateMonica3167040 Feb 04 '20 at 13:45
6

Was trying the following in the lldb pane

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

which errors.

instead use alloc and initWithFormat method:

[[NSString alloc] initWithFormat:@"%@/%@/%@", @"three", @"two", @"one"];
brenjt
  • 15,133
  • 11
  • 74
  • 114
4
NSNumber *lat = [NSNumber numberWithDouble:destinationMapView.camera.target.latitude];
NSNumber *lon = [NSNumber numberWithDouble:destinationMapView.camera.target.longitude];
NSString *DesconCatenated = [NSString stringWithFormat:@"%@|%@",lat,lon];
Tunaki
  • 116,530
  • 39
  • 281
  • 370
Avinash Mishra
  • 754
  • 8
  • 18
4

This is for better logging, and logging only - based on dicius excellent multiple argument method. I define a Logger class, and call it like so:

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

Almost good, except having to end the var args with "nil" but I suppose there's no way around that in 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-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 

In order to only concat strings, I'd define a Category on NSString and add a static (+) concatenate method to it that looks exactly like the log method above except it returns the string. It's on NSString because it's a string method, and it's static because you want to create a new string from 1-N strings, not call it on any one of the strings that are part of the append.

n13
  • 6,568
  • 48
  • 40
3

Try stringWithFormat:

NSString *myString = [NSString stringWithFormat:@"%@ %@ %@ %d", "The", "Answer", "Is", 42];
CommanderHK
  • 1,108
  • 11
  • 7
3

When dealing with strings often I find it easier to make the source file ObjC++, then I can concatenate std::strings using the second method shown in the question.

std::string stdstr = [nsstr UTF8String];

//easier to read and more portable string manipulation goes here...

NSString* nsstr = [NSString stringWithUTF8String:stdstr.c_str()];
iforce2d
  • 7,843
  • 2
  • 25
  • 36
3

You can use NSArray as

NSString *string1=@"This"

NSString *string2=@"is just"

NSString *string3=@"a test"  

NSArray *myStrings = [[NSArray alloc] initWithObjects:string1, string2, string3,nil];

NSString *fullLengthString = [myStrings componentsJoinedByString:@" "];

or

you can use

NSString *imageFullName=[NSString stringWithFormat:@"%@ %@ %@.", string1,string2,string3];
DD_
  • 6,881
  • 11
  • 36
  • 60
Arun
  • 475
  • 6
  • 20
3

My preferred method is this:

NSString *firstString = @"foo";
NSString *secondString = @"bar";
NSString *thirdString = @"baz";

NSString *joinedString = [@[firstString, secondString, thirdString] join];

You can achieve it by adding the join method to NSArray with a category:

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

@[] it's the short definition for NSArray, I think this is the fastest method to concatenate strings.

If you don't want to use the category, use directly the componentsJoinedByString: method:

NSString *joinedString = [@[firstString, secondString, thirdString] componentsJoinedByString:@""];
nhahtdh
  • 52,949
  • 15
  • 113
  • 149
LombaX
  • 16,951
  • 5
  • 49
  • 72
1

Either of these formats work in XCode7 when I tested:

NSString *sTest1 = {@"This" " and that" " and one more"};
NSString *sTest2 = {
  @"This"
  " and that"
  " and one more"
};

NSLog(@"\n%@\n\n%@",sTest1,sTest2);

For some reason, you only need the @ operator character on the first string of the mix.

However, it doesn't work with variable insertion. For that, you can use this extremely simple solution with the exception of using a macro on "cat" instead of "and".

Community
  • 1
  • 1
Volomike
  • 21,378
  • 19
  • 99
  • 188
1

For all Objective C lovers that need this in a UI-Test:

-(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];
}
netshark1000
  • 6,563
  • 8
  • 49
  • 101
0
listOfCatalogIDs =[@[@"id[]=",listOfCatalogIDs] componentsJoinedByString:@""];
user4951
  • 29,779
  • 47
  • 157
  • 270
0

Let's imagine that u don't know how many strings there.

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:@", "];
Resty
  • 113
  • 3
  • 10
0

Inspired by NSMutableString idea from Chris, I make a perfect macro imho. It supports insert nil elements without any Exceptions.

#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 ?: @""];

Example:

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

If you like, you can use id type as parameter by using [VAR description] instead of NSString.

ooops
  • 672
  • 7
  • 18