Assigning NSMutableString from NSString Warning - ios

I have the following three lines of code in my program:
NSMutableString *stringOne = [NSMutableString stringWithFormat:#"Hello "];
NSMutableString *stringTwo = [NSMutableString stringWithFormat:#"World"];
NSMutableString *sayIt = [stringOne stringByAppendingString:stringTwo];
Despite the fact that it works, the third line is causing the warning Assigning NSMutableString * from NSString *.
I am at a loss here since everything I am using is an NSMutableString.

Not quite. stringByAppendingString does not return an NSMutableString. Instead do the following:
NSMutableString *sayIt = [NSMutableString stringWithString:stringOne];
[sayIt appendString:stringTwo];
Or
NSMutableString *sayIt = [[stringOne stringByAppendingString:stringTwo] mutableCopy];

I just realized that stringByAppendingString: returns an NSString despite calling it from an NSMutableString object. Since I am dealing with NSMutableString, I should have used that class's appendString: method. The new code that works without a warning is:
NSMutableString *stringOne = [NSMutableString stringWithFormat:#"Hello "];
NSMutableString *stringTwo = [NSMutableString stringWithFormat:#"World"];
[stringOne appendString:stringTwo];

Related

iOS: changing NSString value

Will this bit of code produce any memory leaks? Is it the correct way to change NSString values?
NSString * enemiesAndElementsTextureFileName = #"bla bla";
enemiesAndElementsTextureFileName = #"bl";
That way of doing it won't cause any memory leaks and it is indeed correct. In this case you wouldn't need an NSMutableString because you aren't altering the string literal itself, you are simply replacing the string value with a new one (replacing #"bla bla" with #"bl").
In this case, however, your string will now be 'bl', so you can delete that first line value and just have NSString * enemiesAndElementsTextureFileName = #"bl";
Yes NSString allocated once. This is one of the way
Yes, use NSMutableString with the following method as your needs:
// Allocate
NSMutableString *str = [[NSMutableString alloc] initWithCapacity:10];
// set string content
[str setString:#"1234"];
// Append
[str appendString:#"567"];
// Concat
[str appendFormat:#"age is %i and height is %.2f", 27, 1.55f];
// Replace
NSRange range = [str rangeOfString:#"height"];//查找字符串height的位置
[str replaceCharactersInRange:range withString:#"no"];
// Insert
[str insertString:#"abc" atIndex:2];
// Delete
range = [str rangeOfString:#"age"];
[str deleteCharactersInRange:range];
NSLog(#"%#", str);

iphone - app crash in a form

In my app, I have a view where user have to fill a form. But, sometime the app crash here, in this function, that simple cacth the value field and built a url to give
-(NSString*)urlToUpload{
NSString *string1 =[[NSString alloc]init];
string1= [NSString stringWithFormat:#"?nombre="];
NSString *string2 = [string1 stringByAppendingString:nameAdded];
//crash here
NSString *string3 = [string2 stringByAppendingString:#"&horario="];
NSString *string4 = [string3 stringByAppendingString:horarioAdded];
NSString *string5 = [string4 stringByAppendingString:#"&info="];
NSString *string6 = [string5 stringByAppendingString:infoAdded];
NSString *string7 = [string6 stringByAppendingString:#"&offerta="];
NSString *string8 = [string7 stringByAppendingString:offertaAdded];
NSString *lat_string = [[[NSString alloc] initWithFormat:#"%f",locationToUpload2.latitude] autorelease];
NSString *lon_string = [[[NSString alloc] initWithFormat:#"%f",locationToUpload2.longitude] autorelease];
NSString *string9 = [string8 stringByAppendingString:#"&latitude="];
NSString *string10 = [string9 stringByAppendingString:lat_string];
NSString *string11 = [string10 stringByAppendingString:#"&longitude="];
NSString *string12 = [string11 stringByAppendingString:lon_string];
NSString *url1 = [NSString stringWithFormat:#"http://myserverside/mysql_up.php"];
NSString *url = [url1 stringByAppendingString:string12];
return url;
}
EDIT:
It seems problem appers on nameAdded when there is a white space into textField(i.e. MisterB not crash, Mister B yes ).
But I am using:
nameAdded =[[nameField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
and NSLOg give of nameAdded is Mister%20B.
The crash still appearing...
Just use a single stringWithFormat::
- (NSString *)urlToUpload {
NSString *url = [NSString stringWithFormat:#"http://myserverside/mysql_up.php?nombre=%#&horario=%#&info=%#&offerta=%#&latitude=%f&longitude=%f",
[nameAdded stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
[horarioAdded stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
[infoAdded stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
[offertaAdded stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
locationToUpload2.latitude, locationToUpload2.longitude];
return url;
}
Make sure the referenced variables are valid.
In your original code there is no need to alloc/init an NSString then assign another string to the same variable. That's a memory leak (string1).
If you really want to structure your code the way you have it, at least use an NSMutableString and append to that one mutable string. Creating over a dozen NSString variables is the wrong way to do it.
Updated: Ensure each of the strings added to the URL are properly escaped.
It looks like nameAdded may be the cause of your problems. Is it nil at that point?
Also
You are allocating a string, setting it to string1 and then immediately setting string1 to the class function stringWithFormat which allocates another string. Also you are using stringWithFormat but you aren't using any format so you could simply use NSString *string1 = #"?nombre=";
Rather than declaring all of those variables you should just use NSMutableString and build it all in one variabl

How to concatenate TextView.text

I have two UITextViews:
self.itemsTextView.text;
self.priceTextView.text;
I want to concatenate these two like so:
NSString *data = self.textView.text + self.itemsTextView.text;
I have tried using a colon, as suggested by this thread, but it doesn't work.
NSString *data = [self.textView.text : self.itemsTextView.text];
For concatenating you have several options :
Using stringWithFormat:
NSString *dataString =[NSString stringWithFormat:#"%#%#",self.textView.text, self.itemsTextView.text];
Using stringByAppendingString:
NSMutableString has appendString:
You may use
NSString * data = [NSString stringWithFormat:#"%#%#",self.textView.text,self.itemsTextView.text];
There are so many ways to do this. In addition to the stringWithFormat: approaches of the other answers you can do (where a and b are other strings):
NSString *c = [a stringByAppendingString:b];
or
NSMutableString *c = [a mutableCopy];
[c appendString b];

Removing last characters of NSString until it hits a separator

I've got a string that shows the stock amount using "-" as separators.
It's built up like this: localStock-wareHouseStock-supplierStock
Now I want to update the supplierStock at the end of the string, but as you can see in the code below it goes wrong when the original string returns more than a single-space value (such as 20).
Is there a way to remove all characters until the last "-" (or remove characters after the second "-")?
NSMutableString *string1 = [NSMutableString stringWithString: p1.colorStock];
NSLog(#"string1: %#",string1);
NSString *newString = [string1 substringToIndex:[string1 length]-2];
NSLog(#"newString: %#",newString);
NSString *colorStock = [NSString stringWithFormat:#"%#-%#",newString,p2.supplierStock];
NSLog(#"colorstock: %#",colorStock);
p1.colorStock = colorStock;
NSLog1
string1: 0-0-0
newString: 0-0
colorstock: 0-0-20
NSLog2
string1: 0-0-20
newString: 0-0-
colorstock: 0-0--20
EDIT: Got it working thanks to Srikar!
NSString *string1 = [NSString stringWithString: p1.colorStock];
NSLog(#"string1: %#",string1);
NSString *finalString = [string1 stringByReplacingOccurrencesOfString:[[string1 componentsSeparatedByString:#"-"] lastObject] withString:p2.supplierStock.stringValue];
NSLog(#"finalString: %#",finalString);
p1.colorStock = finalString;
Why not use componentsSeparatedByString followed by lastObject ?
NSString *supplierStock = [[string1 componentsSeparatedByString:#"-"] lastObject];
The above works if the "stock amount" is always in sets of 3's separated by a "-". Also since you always want supplierStock, lastObject is perfect for your needs.
Of course after splitting string1 with - you get a NSArray instance and you can access the individual components using objectAtIndex:index. So if you want localStock you can get by
NSString *localStock = [[string1 componentsSeparatedByString:#"-"] objectAtIndex:0];
I would suggest splitting the string into the 3 parts using [NSString componentsSeparatedByString:#"-"] and then building it back up again:
NSArray *components = [p1.colorStock componentsSeparatedByString:#"-"];
p1.colorStock = [NSString stringWithFormat:#"%#-%#-%#",
[components objectAtIndex:0],
[components objectAtIndex:1],
p2.supplierStock];
With a string that looks like
NSString *myString = #"Hello-World";
you can separate it with the componentsSeparatedByString: method of the NSString object as
NSArray *myWords = [myString componentsSeparatedByString:#"-"];
The myWords - array will then contain the two NSString objects Hello and World.
To access the strings:
NSString *theHelloString = [myWords objectAtIndex:0];
NSString *theWorldString = [myWords objectAtIndex:1];
Hope it helps!
None of these examples show how to do this if you are unaware of how many of these separator occurrences you're going to have in the original string.
Here's what I believe the correct the correct code should be for dismantling the original string and rebuilding it until you reach the final separator, regardless of how many separators it contains.
NSString *seperator = #" ";
NSString *everythingBeforeLastSeperator;
NSArray *stringComponents = [originalString componentsSeparatedByString:seperator];
if (stringComponents.count!=0) {
everythingBeforeLastSeperator = [stringComponents objectAtIndex:0];
for (int a = 1 ; a < (stringComponents.count - 1) ; a++) {
everythingBeforeLastSeperator = [NSString stringWithFormat:#"%#%#%#", everythingBeforeLastSeperator, seperator, [stringComponents objectAtIndex:a]];
}
}
return everythingBeforeLastSeperator;

Using substringFromIndex on NSMutableString

Why is substringFromIndex not working for my NSMutableString ?
Here code similar to what I have :
NSMutableString *myString = [[NSMutableString alloc] initWithString:#"This is my String"];
[myString substringFromIndex:5];
NSLog(#"myString = %#", myString); //will output This is my String
If I use substringFromIndex on NSString it will work, for example like so :
NSString *tempStr = [[NSString alloc] init];
tempStr = [myString substringFromIndex:5];
NSLog(#"tempStr = %#", tempStr); //will output is my String
Why does it not work in the first example, and I have one more question, if I do it using the second method, and then I set:
[myString setString:tempStr];
[tempStr release];
This will result in a crash, I thought, since I used setString on NSMutableString, that I do not need the NSString and I release it, but apparently that is not the case, however if I use autorelease it will be OK
That method never alters the string you call it on. It returns a new string in both cases. So assign it to a new string variable and your good.
It's crashing because you over releasing one object and and leaking another. You alloc the first string, then make a new autoreleased string from substringFromIndex:, then release it. You dont need to try this hard.
Simply assign the output of the substring method to a variable, and let it be autoreleased for you. No alloc, no release.
A full proper example might look like this:
NSMutableString *myString = [[NSMutableString alloc] initWithString:#"This is my String"];
NSString *tmpString = [myString substringFromIndex:5];
NSLog(#"tempStr = %#", tempString);
[myString setString:tempStr];
// later do [myString release]
or even simpler:
NSString *myString = #"This is my String";
myString = [myString substringFromIndex:5];
You create an NSMutableString specifically so you CAN modify it.
But no one knows any way to do this:
[myMutableString substringFromIndex:5];
And if you are going to do this instead:
myMutableString = [myMutableString substringFromIndex:5];
why even use a mutable in the first place.
MutableStrings are great for ADDING (appending) to them.
Not sure why we can't also shorten (substring) them. (Without making a new copy.)
[myString substringFromIndex:5] returns a new NSString that starts from the specified index. It does not modify myString.
try this code instead:
NSLog(#"myString = %#", [myString substringFromIndex:5]);

Resources