Here are two ways to make a NSString.
NSString *sBody = [NSString stringWithString:#"Hello"]
versus
NSString *sBody = #"Hello"
Most of the time, I see it the first way. But is it also "clean" to use the second, or is it better to not use it?
Thanks and have a nice day!
They are equivalent. It's less code to use the literal (the second example), so I would just use that.
It's the same, the first way you're helping the compiler but it already does a great job optimizing string vars.
Related
The discussions I found about setting NSString constants made me code it the following way:
.h file:
extern NSString * const kSectionHeaders;
.m file:
NSString * const kSectionHeaders = #"header";
As the program runs, it has to test words from a text file against a series of NSString constants.
I read memory comparison should work when setting function like stated above:
if (property == kSectionHeaders) {...}
Doesn't work tough :(
The following works, but it was described as a bad solution (slower, what else?):
if ([property isEqualToString:kSectionHeaders]){...}
I feel I've done something wrong. But can't see what!
Please help :-)
Thanks!
J.
== does pointer comparison, it won't compare the values of two objects. isEqualToString: (and in general isEqual:) is the right way to do this - where was it described as a "bad solution"?
Remember variable names are just pointers to objects in memory.
The == operand compares the pointers. It will not be true unless it is comparing the exact same object in memory.
isEqualToString: is your best bet. Don't worry too much about speed. The devices are plenty fast enough to do the comparison in the blink of an eye. The things that really take noticible time are drawing on screen and reading from disk.
Who described that as a bad solution? It is the only proper/correct solution to the problem at hand.
I have an NSString *str and I want to know if the 2nd character is equal to a. How can I do this? I'm new to objective c.
Use this:
[str characterAtIndex:1]
But I always encourage you to check documentation first!
You could also use:
[[str substringWithRange:NSMakeRange(1,1)] isEqualToString:#"a"];
Admittedly, this only becomes handy when you have longer strings for which you're searching.
What's the difference between NSString *myString = #"Johnny Appleseed" versus NSString *myString = [NSString stringWithString: #"Johnny Appleseed"]?
Where's a good case to use either one?
The other answers here are correct. A case where you would use +stringWithString: is to obtain an immutable copy of a string which might be mutable.
In the first case, you are getting a pointer to a constant NSString. As long as your program runs, myString will be a valid pointer. In the second, you are creating an autoreleased NSString object with a constant string as a template. In that case, myString won't point to a real object anymore after the current run loop ends.
Edit: As many people have noted, the normal implementation of stringWithString: just returns a pointer to the constant string, so under normal circumstances, your two examples are exactly the same. There is a bit of a subtle difference in that Objective-C allows methods of a class to be replaced using categories and allows whole classes to be replaced with class_poseAs. In those cases, you might run into a non-default implementation of stringWithString:, which may have different semantics than you expect it to. Just because it happens to be that the default implementation does the same thing as a simple assignment doesn't mean that you should rely on subtle implementation-specific behaviour in your program - use the right case for the particular job you're trying to do.
Other than syntax and a very very minor difference in performance, nothing. The both produce the exact same pointer to the exact same object.
Use the first example. It's easier to read.
In practice, nothing. You wouldn't ever use the second form, really, unless you had some special reason to. And I can't think of any right now.
(See Carl's answer for the technical difference.)
This works -- it does compile -- but I just wanted to check if it would be considered good practice or something to be avoided?
NSString *fileName = #"image";
fileName = [fileName stringByAppendingString:#".png"];
NSLog(#"TEST : %#", fileName);
OUTPUT: TEST : image.png
Might be better written with a temporary variable:
NSString *fileName = #"image";
NSString *tempName;
tempName = [fileName stringByAppendingString:#".png"];
NSLog(#"TEST : %#", tempName);
just curious.
Internally, compilers will normally break your code up into a representation called "Single Static Assignment" where a given variable is only ever assigned one value and all statements are as simple as possible (compound elements are separated out into different lines). Your second example follows this approach.
Programmers do sometimes write like this. It is considered the clearest way of writing code since you can write all statements as basic tuples: A = B operator C. But it is normally considered too verbose for code that is "obvious", so it is an uncommon style (outside of situations where you're trying to make very cryptic code comprehensible).
Generally speaking, programmers will not be confused by your first example and it is considered acceptable where you don't need the original fileName again. However, many Obj-C programmers, encourage the following style:
NSString *fileName = [#"image" stringByAppendingString:#".png"];
NSLog(#"TEST : %#", fileName);
or even (depending on horizontal space on the line):
NSLog(#"TEST : %#", [#"image" stringByAppendingString:#".png"]);
i.e. if you only use a variable once, don't name it (just use it in place).
On a stylistic note though, if you were following the Single Static Assigment approach, you shouldn't use tempName as your variable name since it doesn't explain the role of the variable -- you'd instead use something like fileNameWithExtension. In a broader sense, I normally avoid using "temp" as a prefix since it is too easy to start naming everything "temp" (all local variables are temporary so it has little meaning).
The first line is declaring an NSString literal. It has storage that lasts the lifetime of the process, so doesn't need to be released.
The call to stringByAppendingString returns an autoreleased NSString. That should not be released either, but will last until it gets to the next autorelease pool drain.
So assigning the result of the the stringByAppendingString call back to the fileName pointer is perfectly fine in this case. In general, however, you should check what your object lifetimes are, and handle them accordingly (e.g. if fileName had been declared as a string that you own the memory to you would need to release it, so using a temp going to be necessary).
The other thing to check is if you're doing anything with fileName after this snippet - e.g. holding on to it in a instance variable - in which case your will need to retain it.
The difference is merely whether you still need the reference to the literal string or not. From the memory management POV and the object creational POV it really shouldn't matter. One thing to keep in mind though is that the second example makes it slightly easier when debugging. My preferred version would look like this:
NSString *fileName = #"image";
NSString *tempName = [fileName stringByAppendingString:#".png"];
NSLog(#"TEST : %#", tempName);
But in the end this is just a matter of preference.
I think you're right this is really down to preferred style.
Personally I like your first example, the codes not complicated and the first version is concise and easier on the eyes. Theres too much of the 'language' hiding what it's doing in the second example.
As noted memory management doesn't seem to be an issue in the examples.
I'll preface my question by saying that I'm a beginner objective-c developer. What is the difference between:
NSString * foo;
NSString* foo;
NSString *foo;
Is there a difference?
All three simply declare a variable named foo of type NSString *. It is really just a matter of style preference.
Some people prefer to put the asterisk next to the type to emphasize that this is a pointer type.
Some people prefer to put the asterisk next to the variable to emphasize the requirements of the language. Every pointer variable in a multiple declaration needs to have the asterisk, as in:
NSString *foo, *bar;
My personal preference is actually the first of your examples with a space before and after the asterisk, reserving the use of an asterisk directly before the variable for use in dereferencing the pointer. I also avoid declaring more than one variable in a single declaration.
There is no difference, they mean all three the same thing. Only it is considered to be better to declare it like:
NSString *foo;
Because when you add a second variable your intention is more clear:
NSString *foo,*bar;
No difference. The three work the same.
The difference is that you have the space in a different location in each example :-)
Semantically, there is no difference whatsoever. Stylistically, the last form is preferred.