So I just got asked this at an interview today and after some googling am still unable to figure out the answer (in fact I couldn't even find any code at all which used the [NSString string] method).
What is the difference between
NSString *someString = [NSString string];
NSString *someString = [[NSString alloc] init];
Now my initial thoughts were that [NSString string] would return an object which would be autoreleased whereas using alloc and init would return an object which has been retained. However it seems that this answer was incorrect.
I've looked at the NSString class reference in the apple docs but all it says is
Returns an empty string.
+ (id)string
Return Value
An empty string.
Could somebody explain to me exactly what the difference between these two are?
Was that your response, and did you ask why your answer was incorrect? I ask because your assumption is mostly correct (at a higher level).
It's not exactly 'retained' when returned from alloc+init, it is an object you hold one reference to, and should balance with a release or autorelease. For the convenience constructor (+[NSString string]), you are returned an object which you hold zero references to, but one which you can expect to live until the current autorelease pool is popped unless you send it an explicit retain (assuming MRC or ARC, since it is tagged iOS).
At the lower level, you could make some guesses, but I wouldn't expect that question in many objc interviews (unless you told them you were mid or senior level). Basically, it is implementation defined, but both forms could return the same static, constant NSString (that may have been what the interviewer was looking for). To illustrate:
#implementation NSString
static NSString * const EmptyNSString = #"";
- (id)init
{
self = [super init];
[self release];
return EmptyNSString;
}
+ (id)string
{
return EmptyNSString;
}
...
Again, that's implementation defined, but an obvious optimization. As well, that optimization makes physically subclassing concrete immutable types (NSString) difficult for mutable variants (NSMutableString) in some cases.
Now my initial thoughts were that [NSString string] would return an object which would be autoreleased
Technically, it’s a placeholder string that is constant, i.e., it lives throughout the entire program execution, never being released. It’s not an autoreleased string. Conceptually, and this is what I’d focus as an interviewer, it’s a string (an empty string) that is not owned by the caller, hence the caller shouldn’t release it.
whereas using alloc and init would return an object which has been retained
Technically, it’s a placeholder string that is constant, i.e., it lives throughout the entire program execution. In fact, it’s the same object as the one above, and it is not retained. Conceptually, and this is what I’d focus as an interviewer, it’s a string (an empty string) that is owned by the caller, hence the caller is responsible for releasing it when it’s not needed any longer.
The correct answer is that
NSString *someString = [NSString string];
gives you an empty string that you do not own and that you must not release (according to the memory management rules)
whereas
NSString *someString = [[NSString alloc] init];
gives you an empty string you do own and that you must release (according to the memory management rules).
Without poking into the implementation, you can't say anything else about those two strings. You can't say that they are autoreleased, because they might not be and you can't say what the retain count will be.
In actual fact, you'll probably get (in both cases) the same pointer to a constant object of some NSString subclass, probably with a retain count of UINT_MAX which is used by the run time as a flag to disable normal retain release behaviour for constant strings. I haven't actually tried the above because nobody except the maintainers of the Objective-C SDK needs to care.
You don't often see
NSString *someString = [NSString string];
because it's the same as
NSString *someString = #"";
which is shorter. It's usually used to create an empty NSMutableString
NSMutableString* s = [NSMutableString string];
The only thing I can imagine is that:
Won't allocate memory since it is not made with alloc. It is a constant (an empty string) made by the system and doesn't need to be released.
You allocate the memory for the NSString yourself which means you have to keep track if the NSString still 'lives' or not when you are done with it, and thus need to release it.
Related
I was just curious, is there any difference between the following two codes?
NSString *aString = [NSString stringWithString:#"a string"];
NSString *aString = #"a string";
I wonder what exactly is going on when you do the latter way.
Both point to a literal string created at compile time.
Even though stringWithString suggest it's autoreleased, a literal string will never get released.
See my related post here:
Difference between NSString literals
From the apple docs # https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Strings/Articles/CreatingStrings.html
Such an object is created at compile time and exists throughout your
program’s execution. The compiler makes such object constants unique
on a per-module basis, and they’re never deallocated, though you can
retain and release them as you do any other object.
What is the proper syntax for accessing an instance variable in Objective-C?
Assume we have this variable:
#interface thisInterface : UIViewController {
NSMutableString *aString;
}
#property (nonatomic, retain) NSMutableString *aString;
and that it is synthesized.
When we want to access it, we first would want to allocate and initialize it. Having programmed in Objective-C for about a month now, I've seen two different forms of syntax. I've seen people do simply aString = [[NSMutableString alloc] initWithString:#"hi"], where they allocate the string like that; I've also seen people start it off with self.aString and then they proceed to initialize their ivar. I guess I'm just trying to figure out what is the most proper way of initializing an instance variable, because with the former example, I have received EXC_BAD_ACCESS errors from it. After prepending the self. though, it didn't appear.
Forgive me if this is a duplicate question, but after reading some posts on SO, it's made me curious. I'm trying to learn the proper syntax with Objective-C because I prefer being proper rather than sloppy.
If you have declared a property and #synthesize it in the .m file, you simply set it like this:
self.aString = #"hi"; // or [[NSMutableString alloc] initWithString:#"hi"];
Using self.varName takes advantage of what your property declaration actually does- it handles retention of the new value (since your property has the retain attribute), releasing the old value, etc for you.
If you just do:
aString = someValue;
... you may be leaking the original value that was in aString, since without using self.aString you are accessing the variable directly vs through the property.
Note the difference between self->varName and self.varName
The first is pointer access. The second is property access.
Why is that important? Pointer access is direct. Property access, on the other hand makes use of getters and setters (be they #synthesized or not). Moreover, as a convenience, the #synthesized accessors take care of the memory mangement for you (i.e. when using self.varName = ...;), whereas varName = ...; does only what it says, i.e. the assignment -> (there lies the explanation for EXC_BAD_ACCESS errors you might be getting).
Syntactically, both forms are correct. If you want to better communicate intent, use self->varName when you want to work directly with the pointer and use self.varName when you want to take advantage of the #property convenience.
Here are all the possible combinations (I think)
OKs and BADs are only correct when aString property has retain attribute:
#property (nonatomic, retain) NSMutableString *aString;
So:
1
aString = [[NSMutableString alloc] init]; //OK:
This is OK but only in the case aString is not pointing to an invalid object or you will loose a reference to that object and it will leak because you won't be able to reach it to release it.
2
aString = [NSMutableString string]; //BAD
Bad because you are suppose to retain aString (as you declared it that way), you are not retaining it and you will get surely get EXC_BAD_ACCESS in the future
3
aString = [[NSMutableString string] retain]; //OK
Same as the first approach, only good if aString is not pointing to a valid object. However I will use the first though.
4
aString = [[[NSMutableString alloc] init] autorelease];//BAD
Same as the second approach.
5
self.aString = [[NSMutableString alloc] init]; //BAD!!
Bad because you are retaining it twice, hence it will lead to memory leaks
6
self.aString = [[NSMutableString string]; //******GOOD!******
This is probably the safest. It will be retained by the property setter and since you are using the setter any other object that could have been pointed by aString will be released appropriately
7
self.aString = [[NSMutableString string] retain]; //BAD
This is retained twice.
8
self.aString = [[[NSMutableString alloc] init] autorelease];//Ok
This is also OK, but I would use the convenience method instead of this long approach :)
Be wary that the #1 and #3 options are perfectly good if you know what you are doing. In fact I use them much more frequently than #6
I personally prefer to use the self. syntax. It just makes it easier to determine that its an instance variable, and not just some other variable in the current scope that will be lost when its NSAutoreleasePool is drained. However, it is correct to use them both ways, and if you are receiving EXC_BAD_ACCESS errors, it is not because you accessed it without using self.. You are correct in saying that you must alloc it, and whichever way you choose to access your variables, keep it consistent or you will receive errors.
I hope this helps.
Always use accessors except in init, dealloc and in accessors themselves. Doing this will save you a lot of headaches like the one you're describing. Also, name your ivars something different than your property (_foo, foo_, mFoo, but not foo).
self.foo is precisely the same as [self foo]. I calls the method foo. self.foo = x is precisely the same a [self setFoo:x]. It calls the method setFoo:. If you synthesized the property foo as a retain variable, then this looks something like:
#synthesize foo = foo_;
- (void)setFoo:(id)value {
[value retain];
[foo_ release];
foo_ = value;
}
This correctly releases the old value of foo_, assigns a new one and retains it.
foo = x (assuming foo is an ivar) does not call any method. None. It just assigns the value of the pointer in x to the pointer in foo. If foo pointed to something that was retained, it's leaked. If the new value you're assigning isn't retained, you'll crash later.
The solution to this is to always use accessors when you can.
Either.
Using the dot syntax is cleaner (to some) and it compiles to the equivalent. i.e self.iVar is the same as [self iVar] and self.iVar = aValue is the same as [self setIVar:aValue];
self.aString is a syntactic sugar to [self aString]. Synthesize a property just create the -aString and -setAString: method (depending on the property you have chosen it while not be the trivial affectation).
Now the question is whether to use the . notation. I suggest you not to use it.
Why? First know that Objective-C aim to be just an addition to C. This mean that every valid C code is also a valid Objective-C code.
Now look at what they have done with the dot notation. The last statement does not hold anymore. You wont distinguish between an access to a field of a C structure and sending objective-c method.
So please don't use the dot notation. Prefer using the [self ..].
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString * str = [[NSString alloc] initWithString:#"test"];
[str release];
int i = 999999999;
while(i-- > 0) {}
NSLog(#"%#", str);
[pool drain];
Output: test
Why didn't release work?
How can I immediately delete the object from memory?
Xcode Version 4.0 iPhone Application
~SOLVED~
Thank's to all for answers.
I've got a lot of useful information about this question. I'm going to use NSString *str = #"text" instead of NSString *str = [[NSString alloc] initWithString:#"text"];
i've understood that release just "marks" memory as "willing to be freed", but not freeing it immediatly
It did work. You have relinquished ownership of that object, and when the system determines that it is no longer owned, it will be marked available for reuse by the system. That may happen immediately, if you were the only owner of the string. It may happen at some later point, if creation of the string caused it to be autoreleased internally. Or, as Dave DeLong points out, the system may optimize it into an object that is never released.
In your case, it's being optimized into a constant string, which will exist for the life of the program. If you were to use an NSMutableString instead of an NSString, you'd see funky behavior that would probably not crash, but wouldn't print what you expected. (See this question for an example.)
If you used an NSArray instead, it would be deallocated when you called release, but you'd still see your NSLog example work correctly until you allocated some other object. Deallocation just marks the memory as available for reuse; it doesn't actually clear it out. So if you passed the array to NSLog, that memory hasn't been changed and thus it still prints correctly.
The key point in all of this, though, is to recognize that calling release will not necessarily cause the object to be deallocated. It may continue to exist for any number of reasons. But once you call release, you have relinquished ownership of the object. If you continue using it after that point, the system is free to do all sorts of weird things at its own will, as demonstrated.
Release does work but what you are attempting to do has undefined behavior, and when using a NSString and a literal you may also get different behavior. What is happening is although your object is released the memory at that location is reclaimable and has not changed and when it goes to print it it is still valid. Since it is a NSString a message to description is not necessarily sent and that is why you are not getting an exception for attempting to message a deallocated object.
This question has some good information about NSString and NSLog.
When you do:
NSString * str = [[NSString alloc] initWithString:#"test"];
This gets optimized into:
NSString * str = #"test";
You can't release a constant string, because it's hardcoded into the application binary.
Proof:
NSString *s = [NSString alloc];
NSLog(#"%p", s);
s = [s initWithString:#"foo"];
NSLog(#"%p", s);
s = #"foo";
NSLog(#"%p", s);
Logs:
2011-04-12 10:17:45.591 EmptyFoundation[6679:a0f] 0x100116370
2011-04-12 10:17:45.599 EmptyFoundation[6679:a0f] 0x100009270
2011-04-12 10:17:45.604 EmptyFoundation[6679:a0f] 0x100009270
You can see that the result of +alloc is different from the result of -initWithString:, and the result of -initWithString: is equivalent to the constant string. Basically, -initWithString: says "aha, i'm going to be an immutable string, and I'm being given an immutable string! I can just take a shortcut, destroy myself, and return the parameter, and everything will still work the same"
You're using a bad pointer in you NSLog(). You happen to be getting lucky in this case, but you should expect code like this to crash or fail in other ways.
There is no need to delete the memory block, this will use up an unneeded cycle.
The memory will be overridden when an new object is allocated an occupy that memory block.
For example look at the following example:
Code1
-(NSString*)getString{
return [[[NSString alloc] initWithFormat:#"test"] autorelease];
}
-(void)printTestString{
NSString *testStr = self.getString;
[testStr retain]
NSLog(#"%#",testStr);
[testStr release]
}
Code2
-(NSString*)getString{
return [[NSString alloc] initWithFormat:#"test"];
}
-(void)printTestString{
NSString *testStr = self.getString;
NSLog(#"%#",testStr);
[testStr release];
}
Code 1 and Code 2 should be valid Code Snippets and no leaks should appear.
Code 1 uses autorelease so the return variable has to be retained in printTestString and after using it released. So there is a small Overhead here because of autorelease.
Code 2 doesn't release the NSString in getString so you have to only release it after using it. Seems your have to write less and you dont have overhead because no autorelease is used.
Which one is the de facto "standard" approach that is used out there?
Another thing I was asking myself. Could the autorelease in getString and the retain with
[testStr retain]
be a problem, when the autorelease pool releases the variable right after
NSString *testStr = self.getString;
then the string would be gone. Is that possible or does the compiler prevent that sort of thing?
Thanks
-Sebo
Do this:
-(NSString*)getString{
return [[[NSString alloc] initWithFormat:#"test"] autorelease];
}
-(void)printTestString{
NSString *testStr = self.getString;
NSLog(#"%#",testStr);
}
Your getString method autoreleases the NSString, which means printTestString doesn't need to retain or release it. Autoreleasing in getString makes sense, because it alloced the object and is therefore the 'owner' of the object. I suggest studying Objective-C's memory management rules before proceeding, as they are very important.
http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/MemoryMgmt/Articles/mmRules.html#//apple_ref/doc/uid/20000994-BAJHFBGH
Jake's answer is correct for almost all of the situations you'll need to return an object from a method, but there are cases where you might want to return something that isn't autoreleased. From the Memory Management Programming Guide (Mac version, but they're the same rules):
You take ownership of an object if you
create it using a method whose name
begins with “alloc” or “new” or
contains “copy” (for example, alloc,
newObject, or mutableCopy), or if you
send it a retain message.
Also, from the Coding Guidelines for Cocoa:
In your methods and functions that
return object values, make sure that
you return these values autoreleased
unless they are object-creation or
object-copy methods (new, alloc, copy
and their variants). “Autoreleased” in
this context does not necessarily mean
the object has to be explicitly
autoreleased—that is, sending
autorelease to the object just before
returning it. In a general sense, it
simply means the return value is not
freed by the caller.
For performance reasons, it’s
advisable to avoid autoreleasing
objects in method implementations
whenever you can, especially with code
that might be executed frequently
within a short period; an example of
such code would be a loop with unknown
and potentially high loop count.
Therefore, methods containing the prefix alloc or new, or those that contain the word copy by convention will have you returning objects that are not autoreleased. In fact, the Clang Static Analyzer understands this convention and will assume non-autoreleased objects being returned from methods that follow these naming rules.
I've used the new prefix in situations where I preferred not to return autoreleased objects (tight loops where I didn't want to manage an autorelease pool, etc.). Again, returning autoreleased objects is what's recommended in almost all cases, but there are some times where you might want to avoid that.
I'm really confused with NSStrings. Like when should I do
NSString *aString = #"Hello";
of should it be:
NSString *aString = [[NSString alloc] initWithString:#"Hello"];
But then its different when you're assigning a value to an NSString property isn't it?
Can someone clear this up for me?
Thanks!!
In general you should do the first, but they are mostly functionally the same. You can treat constant NSStrings just like normal NSString string objects, for instance:
[#"Hello" length]
will return 5. You can assign them to properties, everything just works. The one thing you might notice is that with the constant NSStrings you don't have to worry about retain/release. That is because they are actually mapped into the applications readonly data section, and don't have allocated memory. Retain and release calls against them still work, they just become noops.
NSString *aString = #"Hello";
Will create an autoreleased string. That is, if you don't explicitly retain it, it will might disappear after your method is over (and sometimes that's totally fine). But if you want to hold on to it past that time, you'll need to retain it.
If you create a property for that string like this
#property (retain) NSString *aString;
And then assign like this:
self.aString = #"Hello";
Then you've properly retained the string and it will stick around.
On the other hand, using alloc, init will create a string for you with a retain count of 1, and if you don't need it past that method, you should release it.
****Edit: #"Hello" is not an autoreleased string, as others have pointed out. My bad. ****