objective-c: initialize variable to nil - iphone

Does anyone know if the following code could be problematic:
NSString *addchar = nil;
if (case1)
addChar = [[firstname substringToIndex:1] capitalizedString];
else
addChar = [[fullname substringToIndex:1] capitalizedString];
Assume that firstname and fullname aren't null or empty. Does initializing the NSString object and setting it to 'nil' cause some possible problem? It seems to cause my app to freeze, but only for a very few users, and only those users, but it doesn't have anything to do with different input strings or empty strings. So I'm trying to isolate the problem, but I don't know the difference between
NSString *addChar;
and
NSString *addChar = nil;
Thanks.

Either form is perfectly acceptable. The problem you're having is elsewhere. I recommend doing some code profiling with Instruments to figure out where this issue is occurring.

Without the nil initializer, in some cases your variable may be initialized with garbage (whatever was in the memory space previously). There are specific rules regarding which types of variables (scope-based, static storage, etc.) are nil-initialized automatically for you, but I've always found that it's easier to explicitly initialize all variables instead of memorizing those rules.
That said, because both branches of your if statement clobber any previous value of addChar, there should not be any case in which you can see an invalid value. But it's certainly not hurting anything to explicitly initialize to nil, and if a future maintainer comes along and changes the code paths you might find that the initializer saves you!

You should always initialize to nil if variable is not initialized otherwise.
You can send messages to nil they will be ignored.
NSString * str = nil;
NSLog(#"%#", [str description]);
Outputs:
2009-12-15 08:59:03.352 x[11775] (nil)
Of course I don't need to call description explicitly, I'm just demonstrating call to nil.

There is no difference here since you don't read addChar in your code. Moreover, the compiler may sometimes initialize addChar to nil for you if you don't do it explicitly (depending on the scope of addChar's declaration).
See related question at this place.

From now on, when you use ARC, the strong, weak, and autoreleasing stack variables are initialized to nil:
https://developer.apple.com/library/ios/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011226-CH1-SW5
Additionally, since dawn of times, in ObjC the instance variables are initialized to zero:
Are instance variables set to nil by default in Objective-C?

Related

NSString basics clarification [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
NSString retain Count
I am the beginner for iPhone programming. I am dealing with NSString. I got a doubt explained below.
#implementation Sample;
NSString *str;
-(void)viewDidLoad
{
str = [[NSString alloc] initWithString:#"Hello"];
// Why retain count is some random value? (Eg.2147234)
NSLog(#"retain count of string %d",[str retainCount]);
[str release];
}
-(void)printString
{
// Why the value for "str" getting printed here,
// though its released in viewDidLoad?
NSLog(#"string is %#",str);
}
Don't look at retainCount. It'll confuse you, and it doesn't help.
Constant strings are built right into the code -- they're never allocated or released. It's fine for you to retain and release them as you would any other object, but don't expect a constant string to be deallocated at any point.
In objective-c, an init method doesn't necessarily return the same object created using alloc. It may release self and then return another object.
In the case of initWithString there's a good chance it returns the #"Hello" constant string object, instead of initialising a new string, since it's faster and has no negative side effects (both strings are immutable).
As #Caleb said, normal memory management rules don't apply to constant strings. You can't release it, it will always be there.
But all of this is undocumented behaviour and subject to change. You can't depend on it, and the code you've posted is buggy, after releasing something you shouldn't ever try to access it.
Instead you should follow standard practices, which says you should always release an object and set any pointers to it to nil when you're done with it. If you had set str to nil after releasing it, you would be seeing the expected behaviour.
Or even better, just turn ARC on, and forget about all these things.

Difference between these two NSString methods

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.

Need an iPhone Programmer judge every step and every pointer == nil?

for example:
NSString *myString = [[NSString alloc] init];
if (nil == myString) {
return;
}
Need I do this??Thank you!
No, you don't need to do that, and I can't say I've ever seen code that made pervasive use of that pattern.
Also, the if statement can be shortened to:
if (! myString) {
return;
}
...which is equivalent though no less superfluous. Checking for nil can be useful, but is typically not done immediately after object instantiation. Instead the typical case is to do it to ensure that an object is not over-released, for instance using a pattern like:
if (myObj) {
[myObj release];
myObj = nil;
}
Note that calling any method on nil is allowed in Objective-C, so less harm is caused by an unexpected nil value floating around than in languages like Java where attempting to do anything with a null reference throws an exception.
Objective-C allows to call on nil pointers, that differs the language from many others and allows to skip some checks. Of course, it's still wise to check for == nil in some particular cases, however, you don't have to check every step in the code. Take a look at Apple's documentation and samples and try to follow their style.
Frankly, most iPhone app code produced these days assumes that an out-of-heap condition (the only logical reason for such a simple instantiation operation to fail) never occurs in normal operation. Only when creating large (eg, image) objects might one check for allocation failure.
Of course, init routines can fail for a host of reasons, so checking for nil following a complex instantiation operation may be warranted (depending on the object type). (And remember that many other methods of some objects can return nil under some circumstances as well, so you need to read the specs and code accordingly.)

retain with objective-c

I have a question about a retain and a NSString, if I have a method who a return a NSString, and I put the return NSString in a nsstring variable, I must do a retain or not?
NSString *myString = #"";
myString = [self methodWhoReturnString]; // I must do this?
myString = [[self methodWhoReturnString]retain]; // Or I must do this?
The Apple Developer Documentation on Memory Management explains the scenarios where you retain/release objects.
Simply put, if you want the string to stick around, you need to retain it until you're finished with it. If that is just the scope of the current function, you can get away without retaining it as if the string is already autorelease'd (likely) it won't get released until your function finishes and the current AutoReleasePool is purged.
Bear in mind that an NSString * could actually be pointing to an NSMutableString *. If it matters to you if the string is changed by some other function without you realizing, be sure to copy it: NSString * myCopyOfString = [mystring copy];
If the string is set to autorelease, which it most likely is, then yes you will need to retain it somehow. I would suggest doing this though:
myString = [[self methodWhoReturnString] copy];
this ensures you have retained the data in the string not just a reference to a string that might still be controlled elsewhere. Be sure you release your copy later!
Usually, methodWhoReturnString would return an autoreleased string, which means you should retain it if you want to keep it around.
So, if methodWhoReturnString is your method, I believe that to keep with convention you should return [stringToReturn autorelease]; from that method, and then retain it if you want to keep it.
You use retain if you're going to be using myString at a later point in time (i.e. after the current method has returned) to prevent it being autoreleased.
You don't need to use retain if it's just a temporary variable used within the current method, since in that case you do want it to be autoreleased.
One special case is properties. If you call self.blah = foo, you don't need to retain foo, since the setBlah: method should do it for you.
(there's a whole load of other complexities and edge cases, but this is a good rule of thumb to get you started on understanding what to do)
Given the code you provided, you shouldn't call -retain. In your example, the return value of a method that returns an instance of NSString is assigned to myString, an automatic local variable. If the assignment had been made to an instance variable or a static variable, you would want to call either retain or copy to guarantee that the reference remains valid beyond the end of the local scope.
In this case though, the reference to the NSString instance is stored in a variable that will be destroyed automatically at the end of the local scope, so your code needn't concern itself with the object's lifetime.
Any method that has alloc, new or copy in it automatically retains and infers that you have ownership of the object. All others shouldn't. It would be helpful if you had more context though. If we are in a contained method where this string is used briefly, then you probably don't need to retain. If it is going to be used for a while, you might want to use the #synthesize syntax to make it a property of the class you are in. When you use #property and #synthesize and call something like self.myProperty = something it will automatically retain.

How to release or nil a type-casted object?

I am a bit confused about the objects which are initialized by type-casting. Like
UITextField *txtFld = (UITextField *)[self.view viewWithTag:someTag];
//
//
//some code here for this text field usage
//
//
now when I am finished using this text field should I set it to nil or leave it as it is for the system to take care of it.
Now in the case of the objects of a database class(using sqlite) I create an object like
DatabaseClass *dbObj = (DatabaseClass *)[[appDelegateObject dbObjArray] objectAtIndex:index];
Should I set it to nil too after I am finished with this object
or should initialize the object like:
DatabaseClass *dbObj = (DatabaseClass *)[[[appDelegateObject dbObjArray] objectAtIndex:index] retain];
and then release it and finally set it to nil.
When you type cast like that there is not a new object being created. It just tells the compiler that the object you're using should be treated as if it were, in this case, a DatabaseClass *.
So in this case I believe viewWithTag: is going to returned a object that you won't need to do anything retain/release with unless you're wanting to keep it around as an ivar.
I hope that helps.
The casting is irrelevant here, what's important is how you obtain the reference to the object. There's a good SO question here: Understanding reference counting with Cocoa and Objective-C that covers retain/release issues. Basically, you don't have to do anything in these cases, since you're getting objects back that are not owned by you.
You don't have to cast the type. Objective-C is a dynamic language.
Please correct me if this throws a compiler warning
DatabaseClass = *dbObj = [[appDelegateObject dbObjArray] objectAtIndex:i];
All methods should return autoreleased objects in Cocoa. Exceptions: all copy methods and all alloc methods.
Therefore it's save to not retain/release them because they are autoreleased.
Settings variables to nil has only an effect in a garbage collected environment. As long as you're programming for the iPhone this doesn't matter to you.
But even in a garbage collected environment settings a variable to nil isn't necessary because the compiler should be able to automatically find out which variables aren't needed anymore.
There is an exception to this. You can and sometimes should set an instance's property to nil in a GC environment.