Existe-t-il des raccourcis vers la concaténation de chaînes (stringByAppendingString:
) dans Objective-C ou des raccourcis pour utiliser NSString
en général?
Par exemple, j'aimerais faire:
NSString *myString = @"This";
NSString *test = [myString stringByAppendingString:@" is just a test"];
quelque chose de plus comme:
string myString = "This";
string test = myString + " is just a test";
Deux réponses auxquelles je peux penser… ni l’une ni l’autre n’est aussi agréable à faire qu’un simple opérateur de concaténation.
Commencez par utiliser une méthode NSMutableString
, qui utilise une méthode appendString
, éliminant ainsi le besoin de chaînes temporaires supplémentaires.
Deuxièmement, utilisez un NSArray
pour concaténer via la méthode componentsJoinedByString
.
[NSString stringWithFormat:@"%@/%@/%@", one, two, three];
Je suppose que vous n'êtes pas satisfait de plusieurs ajouts (a + b + c + d), auquel cas vous pouvez faire:
NSLog(@"%@", [Util append:one, @" ", two, nil]); // "one two"
NSLog(@"%@", [Util append:three, @"/", two, @"/", one, nil]); // three/two/one
en utilisant quelque chose comme
+ (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;
}
Si vous avez 2 NSString littéraux, vous pouvez simplement faire ceci:
NSString *joinedFromLiterals = @"ONE " @"MILLION " @"YEARS " @"DUNGEON!!!";
C'est également utile pour rejoindre #defines:
#define STRINGA @"Also, I don't know "
#define STRINGB @"where food comes from."
#define JOINED STRINGA STRINGB
Prendre plaisir.
Je reviens sans cesse sur ce post et je finis toujours par trier les réponses pour trouver cette solution simple qui fonctionne avec autant de variables que nécessaire:
[NSString stringWithFormat:@"%@/%@/%@", three, two, one];
Par exemple:
NSString *urlForHttpGet = [NSString stringWithFormat:@"http://example.com/login/username/%@/userid/%i", userName, userId];
Eh bien, comme les deux points sont une sorte de symbole spécial, mais fait partie de la signature de la méthode, il est possible d'extinguer le NSString
avec la catégorie à ajouter. ce non-idiomatique style de concaténation de chaînes:
[@"This " : @"feels " : @"almost like " : @"concatenation with operators"];
Vous pouvez définir autant d'arguments séparés par des deux-points que vous trouvez utiles ... ;-)
Pour une bonne mesure, j'ai également ajouté concat:
avec des arguments variables qui prennent la liste de chaînes terminée par 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);
}
Créer une méthode:
- (NSString *)strCat: (NSString *)one: (NSString *)two
{
NSString *myString;
myString = [NSString stringWithFormat:@"%@%@", one , two];
return myString;
}
Puis, quelle que soit la fonction dans laquelle vous en avez besoin, définissez votre chaîne, votre champ de texte ou autre sur la valeur de retour de cette fonction.
Ou, pour créer un raccourci, convertissez NSString en chaîne C++ et utilisez le '+' ici.
Utilisez cette manière:
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."];
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:@""]
Cas de test:
- (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");
}
Autre macro: (si vous voulez appliquer un nombre minimum d'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:@""];
Lors de la création de demandes de services Web, je trouve très simple de faire quelque chose comme ceci et de rendre la concaténation lisible dans 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>"
};
Raccourci en créant une macro AppendString (AS) ...
# définir AS (A, B) [(A) stringByAppendingString: (B)]
NSString * myString = @ "This"; NSString * test = AS (myString, @ "n'est qu'un test");
Note:
Si vous utilisez une macro, bien sûr, faites-le simplement avec des arguments variadiques, voir la réponse d'EthanB.
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];
Voici un moyen simple, en utilisant la nouvelle syntaxe littérale de tableau:
NSString * s = [@[@"one ", @"two ", @"three"] componentsJoinedByString:@""];
^^^^^^^ create array ^^^^^
^^^^^^^ concatenate ^^^^^
NSString *myString = @"This";
NSString *test = [myString stringByAppendingString:@" is just a test"];
Après quelques années maintenant avec Objective C, je pense que c’est la meilleure façon de travailler avec Objective C pour atteindre ce que vous essayez d’atteindre.
Commencez à saisir "N" dans votre application Xcode et la complétion automatique en "NSString". saisissez "str" et il complète automatiquement "stringByAppendingString". Donc, les frappes sont assez limitées.
Une fois que vous avez le coup de frapper la touche "@" et que la tabulation du processus d'écriture de code lisible ne devient plus un problème. C'est juste une question d'adaptation.
NSString *result=[NSString stringWithFormat:@"%@ %@", @"Hello", @"World"];
Pourquoi ne pas raccourcir stringByAppendingString
et utiliser un # define:
#define and stringByAppendingString
Ainsi, vous utiliseriez:
NSString* myString = [@"Hello " and @"world"];
Le problème est que cela ne fonctionne que pour deux chaînes, vous devez envelopper des crochets supplémentaires pour plusieurs ajouts:
NSString* myString = [[@"Hello" and: @" world"] and: @" again"];
La seule façon de raccourcir c = [a stringByAppendingString: b]
consiste à utiliser la fonction de saisie semi-automatique autour du point st
. L'opérateur +
fait partie de C, qui ne connaît pas les objets Objective-C.
J'ai essayé ce code. ça a fonctionné pour moi.
NSMutableString * myString=[[NSMutableString alloc]init];
myString=[myString stringByAppendingString:@"first value"];
myString=[myString stringByAppendingString:@"second string"];
J'essayais ce qui suit dans le volet lldb
[NSString stringWithFormat:@"%@/%@/%@", three, two, one];
quelles erreurs.
utilisez plutôt alloc et la méthode initWithFormat
:
[[NSString alloc] initWithFormat:@"%@/%@/%@", @"three", @"two", @"one"];
C’est pour une meilleure journalisation, et uniquement pour la journalisation - basée sur la excellente méthode à plusieurs arguments de dicius. Je définis une classe Logger et l’appelle comme suit:
[Logger log: @"foobar ", @" asdads ", theString, nil];
Presque bon, sauf qu'il faut mettre fin aux arguments avec "nil", mais je suppose qu'il n'y a aucune solution de ce genre dans Objective-C.
Logger.h
@interface Logger : NSObject {
}
+ (void) log: (id) first, ...;
@end
Enregistreur.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
Afin de ne faire que concat chaînes, je définirais une catégorie sur NSString et y ajouterais une méthode de concaténation statique (+) qui ressemble exactement à la méthode de journalisation ci-dessus, sauf qu'elle renvoie la chaîne. C'est sur NSString parce que c'est une méthode de chaîne, et statique car vous voulez créer une nouvelle chaîne à partir de chaînes 1-N, et non l'appeler sur l'une des chaînes faisant partie de l'ajout.
NSNumber *lat = [NSNumber numberWithDouble:destinationMapView.camera.target.latitude];
NSNumber *lon = [NSNumber numberWithDouble:destinationMapView.camera.target.longitude];
NSString *DesconCatenated = [NSString stringWithFormat:@"%@|%@",lat,lon];
Ma méthode préférée est la suivante:
NSString *firstString = @"foo";
NSString *secondString = @"bar";
NSString *thirdString = @"baz";
NSString *joinedString = [@[firstString, secondString, thirdString] join];
Vous pouvez y parvenir en ajoutant la méthode de jointure à NSArray avec une catégorie:
#import "NSArray+Join.h"
@implementation NSArray (Join)
-(NSString *)join
{
return [self componentsJoinedByString:@""];
}
@end
@[]
c'est la définition courte pour NSArray
, je pense que c'est la méthode la plus rapide pour concaténer des chaînes.
Si vous ne souhaitez pas utiliser la catégorie, utilisez directement la méthode componentsJoinedByString:
:
NSString *joinedString = [@[firstString, secondString, thirdString] componentsJoinedByString:@""];
Essayez stringWithFormat:
NSString *myString = [NSString stringWithFormat:@"%@ %@ %@ %d", "The", "Answer", "Is", 42];
Lorsque je traite souvent des chaînes, il est souvent plus facile de créer le fichier source ObjC++. Je peux ensuite concaténer std :: strings en utilisant la deuxième méthode indiquée dans la question.
std::string stdstr = [nsstr UTF8String];
//easier to read and more portable string manipulation goes here...
NSString* nsstr = [NSString stringWithUTF8String:stdstr.c_str()];
Vous pouvez utiliser NSArray en tant que
NSString *string1=@"This"
NSString *string2=@"is just"
NSString *string3=@"a test"
NSArray *myStrings = [[NSArray alloc] initWithObjects:string1, string2, string3,nil];
NSString *fullLengthString = [myStrings componentsJoinedByString:@" "];
ou
vous pouvez utiliser
NSString *imageFullName=[NSString stringWithFormat:@"%@ %@ %@.", string1,string2,string3];
L'un ou l'autre de ces formats fonctionne dans XCode7 lorsque j'ai testé:
NSString *sTest1 = {@"This" " and that" " and one more"};
NSString *sTest2 = {
@"This"
" and that"
" and one more"
};
NSLog(@"\n%@\n\n%@",sTest1,sTest2);
Pour une raison quelconque, vous n'avez besoin que du caractère opérateur @ sur la première chaîne du mélange.
Cependant, cela ne fonctionne pas avec l'insertion de variable. Pour cela, vous pouvez utiliser cette solution extrêmement simple à l'exception de l'utilisation d'une macro sur "cat" au lieu de "et".
Pour tous les passionnés de l’objectif C qui en ont besoin dans un test d’interface utilisateur:
-(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];
}
listOfCatalogIDs =[@[@"id[]=",listOfCatalogIDs] componentsJoinedByString:@""];
Imaginons que vous ne sachiez pas combien de chaînes il y a.
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:@", "];
Dans Swift
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"
De plus, vous pouvez utiliser l’opérateur +=
comme ci-dessous ...
var str3 = "Some String"
str3 += str2 // str3 would be "Some String is just a test"