Objective-c 中用于连接 NSStrings 的捷径

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

转载于:https://stackoverflow.com/questions/510269/shortcuts-in-objective-c-to-concatenate-nsstrings

csdnceshi51
旧行李 Just in case anyone is curious, in Swift you are able to use let name = "Long" + "face"
接近 4 年之前 回复
csdnceshi69
YaoRaoLov 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.
4 年多之前 回复
csdnceshi79
python小菜 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.
大约 5 年之前 回复
csdnceshi68
local-host 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...
5 年多之前 回复
csdnceshi68
local-host 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.
5 年多之前 回复
csdnceshi68
local-host 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().
5 年多之前 回复
csdnceshi75
衫裤跑路 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.
5 年多之前 回复
csdnceshi71
Memor.の Things are changed now : Swift (apple new language) is more straightforward
5 年多之前 回复
csdnceshi55
~Onlooker You expectation of a + operator for strings in Objective-C belies a fundamental misunderstanding of Objective-C's design & legacy.
接近 6 年之前 回复
csdnceshi68
local-host You mean "[...]Which is then compiled again to machine code, at runtime, just in time".
大约 6 年之前 回复
weixin_41568174
from.. Interpreted language? C# and Java are compiled languages. Compiled to bytecode, which is then compiled again to machine code.
大约 6 年之前 回复
csdnceshi68
local-host ...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.
6 年多之前 回复
weixin_41568134
MAO-EYE This is not the only feature that Objective-C lacks. There are dozens of others. Quoting from the link 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.
6 年多之前 回复
csdnceshi60
℡Wang Yan Wow that's cool... using C++ on top of Objective-C for operator overloading. Now that warrants some looking into.
6 年多之前 回复
csdnceshi60
℡Wang Yan Forget the @ symbol, just make Obj-C support operator overloading like C++ does! That's what I want.
6 年多之前 回复
csdnceshi73
喵-见缝插针 I'd just like to propose '@+' as a concatenation operator. I'll expect this in the next update to Objective-C, kthxbai
接近 7 年之前 回复
csdnceshi68
local-host 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).
7 年多之前 回复
csdnceshi57
perhaps? ever heard of ARC?
7 年多之前 回复
csdnceshi64
游.程 Shortest hack in obj-c syntax would be [@"This" : @" works" : @" OK"]; when you extend the NSString with your own category. See answer below.
7 年多之前 回复

29个回答

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.

csdnceshi51
旧行李 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.
5 年多之前 回复
weixin_41568134
MAO-EYE The [NSString stringWithFormat:@"%@/%@/%@", three, two, one]; technique seems the most elegant. It should be the selected answer.
5 年多之前 回复
csdnceshi54
hurriedly% with the new array literal syntax, it is even better.
6 年多之前 回复
csdnceshi73
喵-见缝插针 +1 for this answer. [NSMutableString appendString] is more memory friendly than [NSString stringByAppendingStrings].
大约 8 年之前 回复
weixin_41568183
零零乙 +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:@" "];
接近 10 年之前 回复
csdnceshi76
斗士狗 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.
接近 10 年之前 回复

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;
}
csdnceshi52
妄徒之命 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.
4 年多之前 回复
csdnceshi65
larry*wei 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?
大约 5 年之前 回复
weixin_41568208
北城已荒凉 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.
大约 8 年之前 回复
weixin_41568174
from.. 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.
接近 10 年之前 回复

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.

weixin_41568110
七度&光 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.
大约 2 年之前 回复
csdnceshi79
python小菜 neither worked.
2 年多之前 回复
csdnceshi57
perhaps? how is TABLE_NAME defined?
2 年多之前 回复
csdnceshi79
python小菜 in program error :(
2 年多之前 回复
csdnceshi64
游.程 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)
6 年多之前 回复
csdnceshi61
derek5. You actually don't need the @s on the strings after the first. @"I" " really" " enjoy"...
6 年多之前 回复
csdnceshi57
perhaps? :) But this works only with literals not with dynamically created NSString instances.
接近 7 年之前 回复

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:@""];
csdnceshi68
local-host 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.
大约 3 年之前 回复
csdnceshi56
lrony* Haven't checked this question in a while, but I'm leaning towards accepting this as the right answer after all these years!
接近 4 年之前 回复
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];
NSString *result=[NSString stringWithFormat:@"%@ %@", @"Hello", @"World"];

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

Try stringWithFormat:

NSString *myString = [NSString stringWithFormat:@"%@ %@ %@ %d", "The", "Answer", "Is", 42];
csdnceshi57
perhaps? Why does this have 2 downvotes? Is it because this was already mentioned in another answer?
接近 7 年之前 回复

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.

共29条数据 1 3 尾页
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!