What is the best way to initialize NSMutableString object? - iphone

If I take a following question. What is the best way to initialize NSMutableString Class?
(All instance will be return at unexpected times... so I'll assume that the initialization as follows:)
If I know in advance the amount of work. ( expected )
NSMutableString *str1 = [NSMutableString stringWithString:#""];
NSMutableString *str2 = [NSMutableString stringWithCapacity:0];
NSMutableString *str3 = [NSMutableString stringWithCapacity:1000];
NSMutableString *str4 = [NSMutableString string];
for(int i = 0; i< 1000; i++)
{
//The following tasks.(Adding to the string to continue working.)
[/*str1~str4*/ appendFormat:#"%d", i];
}
If I don't know in advance the amount of work. ( unexpected )
NSMutableString *str1 = [NSMutableString stringWithString:#""];
NSMutableString *str2 = [NSMutableString stringWithCapacity:0];
NSMutableString *str3 = [NSMutableString stringWithCapacity:1000];
NSMutableString *str4 = [NSMutableString string];
for(int i = 0; i< /*a large of size(unpredictable)*/ ; i++)
{
//The following tasks.(Adding to the string to continue working.)
[/*str1~str4*/ appendFormat:#"%d", i];
}
Largely split into two when performing these tasks, What is the best way to initialize?
I sometimes when working with these task is also confusing.

Case 1
Of the options listed, I'd use:
NSMutableString *str3 = [NSMutableString stringWithCapacity:1000];
…if you know the destination size, or estimate it with a little room at the top and are able to quickly determine the exact size, or the size worst case scenario, this could save multiple reallocate and copy operations. If you don't know the size in the worst case scenario, or if it takes a lot of time to calculate, then you may as well use [NSMutableString string] or [NSMutableString new]. Also, *WithCapacity is a hint, which the frameworks are free to ignore.
Of course, the body of your loop and the size you reserve also implies that all the values are [0…9] (specifically, that all values consume one character), and you could in that case likely do far better by using format strings with more arguments. However, i is obviously larger than 9 for most iterations, and will consume on average 3 characters each, so 3000 would be a more appropriate reserve capacity for the exact code you posted.
Case 2
Of the options listed, I'd use:
NSMutableString *str4 = [NSMutableString string];
Even better, if you don't need to add it to an autorelease pool: [NSMutableString new] or [[NSMutableString alloc] init].
Other Notes
Yes, keeping objects out of autorelease pools (e.g. use alloc+init) can improve performance and reduce peak memory usage significantly. Sometimes, this is beyond your control, and in some environments (e.g. ARC), this may happen even though you use an autoreleased convenience constructor - e.g. [NSMutableString string].
The Faster Solution
Finally, if this case you have outlined really is a performance concern, the fastest way would be to create a char buffer on the stack and then create one NSString from the result of copying the numbers over to the char buffer. Assuming your ints are all 0-9, it would be very fast and easy, then simply create an NSString from the (terminated) cstring. You can even do this if the input size varies, or is very large (results in a very long string).

It doesn't really matter.
If you've optimized your program so far that this decision will have a measurable effect on its overall performance, pat yourself on the back or, as Sheldon from BBT would say, "have a chocolate!"
PS:
If you precisely know the size up front or have a really good estimate on it, then use that size in stringWithCapacity: or initWithCapacity: if you don't, then don't even bother — let the framework decide, it's pretty damn clever!

Here is the shortest way:
NSMutableString *string = [#"" mutableCopy];

NSMutableString *str1 = [NSMutableString stringWithString:#""];
Bad, a NSString (#"") is pointlessly created, then copied into a new NSMutable String
NSMutableString *str2 = [NSMutableString stringWithCapacity:0];
Bad, a NSMutableString with 0 capacity will need to be inflated upon the first addition to it.
NSMutableString *str3 = [NSMutableString stringWithCapacity:1000];
Good, if 1000 has some significance (i.e. it's an expected size for the content you're working with).
NSMutableString *str4 = [NSMutableString string];
Good, using a convenience method, which is is like doing [NSMutableString alloc] init];

If you know the size upfront, use
[NSMutableString stringWithCapacity: _Known_Size_];
If you don't know the size up front, use
[NSMutableString stringWithCapacity: _small_number_];
Then the mutable string will grow as it needs to.

In Swift 5:
var mutableString = NSMutableString("")

It is always better to allocate and initialize an object, not use a class method to create it (which puts it in the closest autorelease pool).
So,
NSMutableString* stringOne = [[NSMutableString alloc] initWithCapacity:capacity];
instead of
NSMutableString* stringTwo = [NSMutableString stringWithCapacity:capacity];
Just remember that you have to release stringOne when you are done with it, but not stringTwo, because the stringWithCapacity: class method returns an autoreleased object.
Read more about the topic here: http://www.mulle-kybernetik.com/artikel/Optimization/opti-5.html

Related

variable is not a CFStringRef

I have this:
partenaire_lat = 48.8160525;
partenaire_lng = 2.3257800;
And obtain a NSString like this:
NSString *endPoint =[NSString stringWithFormat:#"%#,%#", partenaire_lat, partenaire_lng];
and after using this NSString in some context I get this stupid error:
Variable is not a CFString.
But if I create the NSString like this:
endPoint = #"48.8160525,2.3257800" it then works perfect!
For this error Variable is not a CFString I tried the following:
NSString *endPoint1 =[NSString stringWithFormat:#"%#,%#", partenaire_lat, partenaire_lng];
CFStringRef endPoint =(CFStringRef)endPoint1;
and tried to use endPoint but not working neither this way.Anyone any miraculous idea?Thx
EDIT:partenaire_lat and partenaire_lng are both NSString!!
You have
partenaire_lat = 48.8160525;
partenaire_lng = 2.3257800;
You keep saying that the two variables are NSStrings but you aren't assigning NSStrings to them. You need to assign NSString objects to NSString variables - they aren't created for you automatically.
So the answers which are telling you to use formatted strings are correct. You really should be doing it like this:
partenaire_lat = [[NSString stringWithFormat:#"%f", 48.8160525] retain];
partenaire_lng = [[NSString stringWithFormat:#"%f", 2.3257800] retain];
what are lat and lng? i'm assuming float or double..so you should use [NSString stringWithFormat:#"%f,%f", lat, lng]; (or however you want the floats to be formatted)
You code has several potential problems:
%# format specifier expects object parameter, while it looks like you pass plain float (I may be wrong here as there's not enough context to be sure). Change format to %f to fix your problem if that's really the case:
NSString *endPoint1 =[NSString stringWithFormat:#"%f,%f", partenaire_lat, partenaire_lng];
Your endPoint1 string is autoreleased and may become invalid outside of current scope if you don't retain it. So if you try to use your variable in another method you probably should retain it.
All you need to do
NSString *latStr=[[NSNumber numberWithFloat:partenaire_lat] stringValue];
NSString *lngStr=[[NSNumber numberWithFloat:partenaire_lng] stringValue];
and do whatever you want to do with these two string :)

Create Unsigned Long Long from NSString [duplicate]

This question already has an answer here:
Closed 11 years ago.
Possible Duplicate:
Storing and retrieving unsigned long long value to/from NSString
I am trying to create a unsigned long long from a string so I can use the value in elsewhere but not having much luck doing so...Here is what I am using to attempt this
-(void)unsignedLongValue{
NSString *theString = [NSString stringWithFormat:#"%llu", [NSNumber
unsignedLongLongValue]];
theString = [[_message objectForKey:#"user"] objectForKey:#"id"];
NSLog(#"%llu");
}
If you have any suggestions or know of any good articles I would be very much appreciative if you could inform me! thanks!
You probably want to do this,
NSString * theString = [[[_message objectForKey:#"user"] objectForKey:#"id"];
NSNumberFormatter * numberFormatter = [[[NSNumberFormatter alloc] init] autorelease];
NSNumber * number = [numberFormatter numberFromString:theString];
NSLog(#"%llu", [number unsignedLongLongValue]);
The line
NSLog(#"%llu");
does nothing. You need to tell the log what to print, not just what type it is. Use this instead:
NSLog(#"%llu",numberToPrint);
Also, you re-write theString immediately after defining it, so the initial value from
NSString *theString = [NSString stringWithFormat:#"%llu", [NSNumber unsignedLongLongValue]];
is never used.

Reusing NSMutableString correctly on the iPhone

Using objective-c on the iPhone, what is wrong with this code?
Is it leaking memory? Why?
How would I do this correctly?
NSMutableString *result = [NSMutableString stringWithFormat:#"the value is %d", i];
... then later in my code... I might need to change this to:
result = [NSMutableString stringWithFormat:#"the value is now %d", i];
I need to use stringWithFormat a 2nd time... but isn't that creating a NEW string and not correctly freeing the old one?
No, it doesn't leak memory because stringWithFormat: returns an autoreleased object.
You could use the instance method "setString" for your already existing NSMutableString, like this:
[ result setString:[NSString stringWithFormat:#"the value is now %d", i] ];
If you really want to reuse the string, you can use something like
[result setString:#""];
[result appendFormat:#"the value is now %d", i];
However, unless you notice a performance/memory problem, just use
NSString *result = [NSString stringWithFormat:#"the value is %d", i];
/* ... */
result = [NSString stringWithFormat:#"the value is now %d", i];
It's generally easier to work with immutable objects because they can't change under your feet.
What you have seems to me to be the natural way to replace a mutable string with new content, unless you have other references to the same mutable string elsewhere.
If you don't have other references to it and you are reusing the string only to improve performance/memory footprint, that sounds like premature optimisation.
By the way, you do not own a string you obtain via stringWithFormat: so you do not need to (Indeed must not) release it.

unichar and NSString - how interchangeable are these?

There is an NSString method -characterAtIndex: which returns an unichar.
(unichar)characterAtIndex:(NSUInteger)index
I wonder if this unichar, which obviously is not an NSString, can be converted into an NSString or feeded to an NSString for comparing purposes?
And: Does an NSString internally just consist of an array of unichar items?
You have two options: the first is a category adding a stringWithUnichar method to NSString:
#interface NSString (MNNSStringWithUnichar)
+ (NSString *) stringWithUnichar: (unichar) value;
#end
#implementation NSString (MNNSStringWithUnichar)
+ (NSString *) stringWithUnichar:(unichar) value {
NSString *str = [NSString stringWithFormat: #"%C", value];
return str;
}
#end
Then call it with
NSString *otherString = #"TestString";
NSString *str = [NSString stringWithUnichar:[otherString characterAtIndex:1]];
or you could just directly go like this:
NSString *str = [NSString stringWithFormat:#"%C",[otherString characterAtIndex:1]];
Choose the category if you want to use it repeatedly, or if you only have to do it once, use the stringWithFormat example!!
Not to sure about the internals of NSString, but I'd guess it is probably wrapping a
unichar *
or an array of unichars (like a C char *)
A unichar is simply a 16bit value that is used to store a character. Unlike an unsigned char which is only 8 bits, it can hold more than 0-255, so it can hold unicode characters as well, which are 16bits. A NSString is a (cluster of) class[es] that contains an array of unichars
EDIT
Here are a few articles about what people think an NSString is:
http://cocoawithlove.com/2008/08/string-philosophies-char-arrays.html
http://www.reddit.com/r/programming/comments/6v1yw/string_philosophies_char_arrays_stdstring_and/
Another option is to use the class method:
+ (id)stringWithCharacters:(const unichar *)characters length:(NSUInteger)length;
So just using:
yourString = [NSString stringWithCharacters: &yourChar length: 1];
The yourChar parameter must be a pointer.
NSString is really a class cluster. That means for various reasons including performance based on content and size and to support toll free bridging to CFString when you create an NSString you may actually get one of many private classes that return YES to isKindOf: when you ask it if it is an NSString and it will respond to all of the methods in the NSString class. It's like a Protocol but all objects will say and do and be NSString in the public API.
As the documentation states for NSString and CFString it is conceptually an array of UTF16 unichar
It may and will use a different internal representation where it presents an advantage to the implementation. Usually performance sometimes memory size. But you can rely on it giving you a C array of unichar when asked or anything else the API promises.
It's had a long time to mature and is tweaked internally in nearly every release.
In short yes you can think of it as being backed by an array of UTF16 unichar largely matching the description of a logical string in the Unicode standard. But the thing to keep in mind is that you really should not need to worry what's inside, only what it tells you is inside.
It's one of the best implementations of Unicode.
If you want a fuller picture of how it works you can look at ( most ) of the source of CFString at opensource.apple.com
It's C and Core Foundation (object oriented C) and fairly stylized, so don't expect to understand it all at once.
NSString and CFString do have methods to return and create from unichar. Most people should not need those most of the time.
If you do, be careful, be prepared to read a lot and to make naive mistakes. Unicode is a big topic. Handling it correctly is a science and an art at that level. That is one of the reasons for NSString. It handles a lot of the hard stuff so you do not have to so often, unless you want to or need to.

How to concatenate two strings on iPhone?

How to connect string "Hello" and string "World" to "HelloWorld"? Looks like "+" doesn't work.
NSString *string = [NSString stringWithFormat:#"%#%#", #"Hello", #"World"];
NSLog(#"%#", string);
That should do the trick, although I am sure there is a better way to do this, just out of memory. I also must say this is untested so forgive me. Best thing is to find the stringWithFormat documentation for NSString.
How about:
NSString *hello = #"Hello";
NSString *world = #"World";
NSString *helloWorld = [hello stringByAppendingString:world];
If you have two literal strings, you can simply code:
NSString * myString = #"Hello" #"World";
This is a useful technique to break up long literal strings within your code.
However, this will not work with string variables, where you'd want to use stringWithFormat: or stringByAppendingString:, as mentioned in the other responses.
there's always NSMutableString..
NSMutableString *myString = [NSMutableString stringWithString:#"Hello"];
[myString appendString: #"World"];
Note:
NSMutableString *myString = #"Hello"; // won't work, literal strings aren't mutable
t3.text=[t1.text stringByAppendingString:t2.text];
Bill, I like yout simple solution and I'd like to note that you can also eliminate the space between the two NSStrings:
NSString * myString = #"Hello"#"World";