Message body text + label.text - objective-c

I want to create a message that has a string text and also reference a label's text too.
I have this, but I'm not sure how to tie it together.
NSString *message = #"Lets meet here:"; _addressLabel.text;

You can use stringWithFormat:
NSString *message = [NSString stringWithFormat:#"Lets meet here: %#", _addressLabel.text];
The %# tells the method where to substitute the argument - you can even have multiple:
NSString *foo = #"foo";
NSString *bar = #"bar";
NSString *message = [NSString stringWithFormat:#"%# : %#", foo, bar];
will make message be foo : bar.

Related

Include a variable in the middle of NSString

I currently tried to use this:
NSString *hello = #"Hello";
NSString *whatever = [hello stringByAppendingString:#", world!"];
it's possible to use this but it will make a lot of work because my goal is to do something like this:
NSString = "Hello" +variable+ "My name is" +variable + ",Good day"
You can use NSString's method stringWithFormat
example
NSString *str = [NSString stringWithFormat:#"Hello %# My Name is %# ",var1,var2]
or
NSString *str = [NSString stringWithFormat:#"Hello %# My Name is %# ",#"Stack Overflow",#"FreelancsAndroidLovesyou"]
You can do this alternatively, if both values are same then you can do this,
NSString *string = #"Hello YOUR_NAME, My name is YOUR_NAME, Good day";
string = [string stringByReplacingOccurrencesOfString:#"YOUR_NAME" withString:#"Your_desired_Name"];
UPDATE
If both values are different then you can do this,
NSString *string = #"Hello %#, My name is %#, Good day";
NSString *output = [NSString stringWithFormat:string, variable1, variable2];
You can use the NSString method stringWithFormat.
Objective C
NSString *strConcat = [NSString stringWithFormat:#"Hello %# My Name is %# ",var1,var2];
Swift
let strConcat = "Hello "+ strOne + " My Name is " + strTwo
OR
let strConcateSecond = "Hello \(strOne) My Name is \(strTwo)"

Making a backspace button for a calculator

I am making an iOS calculator and it I'm having minor difficulties with the backspace button (for deleting the last number of the value displayed on a label).
To get the current value on the label I use
double currentValue = [screenLabel.text doubleValue]
Following other questions, I tried something like
-(IBAction)backspacePressed:(id)sender
{
NSMutableString *string = (NSMutableString*)[screenLabel.text];
int length = [string length];
NSString *temp = [string substringToIndex:length-1]
;
[screenLabel.text setText:[NSString stringWithFormat:#"%#",temp]];
}
But it does not work,
(Xcode says "setText is deprecated", "NSString may not respond to setText" and that an identifier is expected in the first line of code inside the IBAction)
and I do not really understand this code to make it work by myself.
What should I do?
It should be
[screenLabel setText:[NSString stringWithFormat:#"%#",temp]];
Your Xcode clearly says that you are trying to call setText' method on anNSStringwhere as you should be calling that on aUILabel. YourscreenLabel.textis retuning anNSString. You should just usescreenLabelalone and should callsetText` on that.
Just use,
NSString *string = [screenLabel text];
The issue with that was that, you are using [screenLabel.text]; which is not correct as per objective-c syntax to call text method on screenLabel. Either you should use,
NSString *string = [screenLabel text];
or
NSString *string = screenLabel.text;
In this method, I dont think you need to use NSMutableString. You can just use NSString instead.
In short your method can be written as,
-(IBAction)backspacePressed:(id)sender
{
NSString *string = [screenLabel text];
int length = [string length];
NSString *temp = [string substringToIndex:length-1];
[screenLabel setText:temp];
}
As per your question in comments(which is deleted now), if you want to display zero when there are no strings present, try,
-(IBAction)backspacePressed:(id)sender
{
NSString *string = [screenLabel text];
int length = [string length];
NSString *temp = [string substringToIndex:length-1];
if ([temp length] == 0) {
temp = #"0";
}
[screenLabel setText:temp];
}

Concatenate String in String Objective-c

I want to place a string within a string. Basically in pseudo code:
"first part of string" + "(varying string)" + "third part of string"
How can I do this in objective-c? Is there a way to easily concatenate in obj-c? Thanks!
Yes, do
NSString *str = [NSString stringWithFormat: #"first part %# second part", varyingString];
For concatenation you can use stringByAppendingString
NSString *str = #"hello ";
str = [str stringByAppendingString:#"world"]; //str is now "hello world"
For multiple strings
NSString *varyingString1 = #"hello";
NSString *varyingString2 = #"world";
NSString *str = [NSString stringWithFormat: #"%# %#", varyingString1, varyingString2];
//str is now "hello world"
Variations on a theme:
NSString *varying = #"whatever it is";
NSString *final = [NSString stringWithFormat:#"first part %# third part", varying];
NSString *varying = #"whatever it is";
NSString *final = [[#"first part" stringByAppendingString:varying] stringByAppendingString:#"second part"];
NSMutableString *final = [NSMutableString stringWithString:#"first part"];
[final appendFormat:#"%# third part", varying];
NSMutableString *final = [NSMutableString stringWithString:#"first part"];
[final appendString:varying];
[final appendString:#"third part"];
NSString * varyingString = ...;
NSString * cat = [NSString stringWithFormat:#"%s%#%#",
"first part of string",
varyingString,
#"third part of string"];
or simply -[NSString stringByAppendingString:]
You would normally use -stringWithFormat here.
NSString *myString = [NSString stringWithFormat:#"%#%#%#", #"some text", stringVariable, #"some more text"];
Just do
NSString* newString=[NSString stringWithFormat:#"first part of string (%#) third part of string", #"foo"];
This gives you
#"first part of string (foo) third part of string"
Iam amazed that none of the top answers pointed out that under recent Objective-C versions (after they added literals), you can concatenate just like this:
#"first" #"second"
And it will result in:
#"firstsecond"
You can not use it with NSString objects, only with literals, but it can be useful in some cases.
simple one:
[[#"first" stringByAppendingString:#"second"] stringByAppendingString:#"third"];
if you have many STRINGS to Concatenate, you should use NSMutableString for better performance

Append a NSString as the first line of another NSString

I have two NSString, A and B.
I would that A becomes B\nA.
How can I do?
If in a method I use
NSString *string_B = [[NSString alloc] initWithString:#"something_from_a_DB"];
NSString *string_A = [[NSString alloc] initWithString:#"something_from_a_DB"];
if (aTrueCondition) {
string_C = [NSString stringWithFormat:#"%#\n%#", string_B, string_A];
} else {
string_C = string_A;
}
is string_C = string_A; a memory leak or is it good?
I added [string_A release], as string_C is a retained property. Now it works.
This is the way to put them together:
NSString *newString = [NSString stringWithFormat:#"%#\n%#", stringB, stringA];
The second part is “A becoming newString”. This is hard to do, as regular strings are immutable in Cocoa. The best thing you can do is throw out the old A and point A to the new string:
NSString *strA = #"foo";
NSString *strB = #"bar";
strA = [NSString stringWith…];
Just be careful not to leak A:
NSString *strA = [[NSString alloc] initWithString:#"foo"];
strA = [NSString stringWith…]; // this is a leak
NSString *str=[NSString stringWithFormat:#"%#\n%#",B,A];
use this.
NSString *stringA = [NSString stringWithFormat:#"%#\n%#", stringB, stringA];

Shortcuts in Objective-C to concatenate 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";
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;
}
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.
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.
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];
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.
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);
}
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."];
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:#""];
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>"
};
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.
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];
Here's a simple way, using the new array literal syntax:
NSString * s = [#[#"one ", #"two ", #"three"] componentsJoinedByString:#""];
^^^^^^^ create array ^^^^^
^^^^^^^ concatenate ^^^^^
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.
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.
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"];
NSString *result=[NSString stringWithFormat:#"%# %#", #"Hello", #"World"];
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];
I tried this code. it's worked for me.
NSMutableString * myString=[[NSMutableString alloc]init];
myString=[myString stringByAppendingString:#"first value"];
myString=[myString stringByAppendingString:#"second string"];
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"];
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.
NSNumber *lat = [NSNumber numberWithDouble:destinationMapView.camera.target.latitude];
NSNumber *lon = [NSNumber numberWithDouble:destinationMapView.camera.target.longitude];
NSString *DesconCatenated = [NSString stringWithFormat:#"%#|%#",lat,lon];
Try stringWithFormat:
NSString *myString = [NSString stringWithFormat:#"%# %# %# %d", "The", "Answer", "Is", 42];
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()];
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:#""];
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];
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".
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];
}
listOfCatalogIDs =[#[#"id[]=",listOfCatalogIDs] componentsJoinedByString:#""];
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:#", "];
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.