When to use properties and allocation initializing - iphone

I was just working on my application where I needed to set an instance variable of NSMutableData a value. Now I also created a property for my instance variable which means that my program automatically allocates it etc, right? But then I assigned it a value but it was not taking it but staying null. I then manually allocated it and then it suddenly accepted the value. So now my question is what is the need for properties and why do I have to manually allocate my instance variable although I have a property set up for it?
Thanks in advance!
edit: my code:
in my .h file I have
#interface FirstScreen : UIViewController{
NSMutableData* fetchedData;
}
#property(nonatomic, retain)NSMutableData*fetchedData;
in my .m file I have:
-(void) connectionDidFinishLoading:(NSURLConnection *)connection{
NSString* fetchedDataString= [[NSString alloc]initWithData:fetchedData encoding:NSUTF8StringEncoding];
}
Now if I do not implement:
-(void)viewDidLoad{
self.fetchedData=[[NSMUtableData alloc]init];
}
fetchedDataString does not have any value. However if it is allocated it has a value. I am confuces when to allocate instance variables and when not to.

It doesn't allocate. All properties do for you is define the instance variable & implement accessor methods.
I'm assuming by "assigning a value" you mean trying to set the contents of the NSMutableData object you thought had been allocated for you.

Now I also created a property for my instance variable which means
that my program automatically allocates it etc, right?
Wrong. If you synthesize accessors for the property, an ivar will also be created for it if you haven't created one. But your property is just a pointer... it doesn't point to anything until you create an object for it to point to, and set it:
self.fetchedData = [[NSMutableData alloc] init];

That's C. What you're saying is true for every single variable, whether it's local or an instance variable. It's one thing to declare storage for a variable (that's all you're doing by declaring a property). It's another to give it a value. This declaration in code:
NSMutableArray* arr;
...does not cause arr to take on any particular value (under ARC it's nil; prior to ARC it could be anything at all). It is certainly not an empty mutable array! But that's exactly analogous to what you're doing when you declare a property.
If this is the first value the variable is to adopt, that's called initializing. You might say in code:
NSMutableArray* arr = [NSMutableArray array];
But you can't do that in a property declaration, so you have to initialize at some later time while the code is running. A typical approach is to do this in your designated initializer, so that no matter what happens later there will be an actual array at this address, from very early on.
I've written a book on this topic (iOS programming), and the chapter dealing with the issue you're having is free to read online:
http://www.apeth.com/iOSBook/ch03.html

Related

ARC : Is this approach correct

This may sound a newbie question however I'm new to iOS dev.
I've following code in my project, the project is ARC enabled, and I get error on its execution (bad access), and would like to understand the cause of the problem and solve it.
on some button press following code is invoked in MTClassA.m file
-(void) someMethod
{
for (int i = 0; i < N; i++) {
...
(param1 and param2 are location variables)
...
mFlickr = [[MTFlickr alloc] initWithParam1:param1 param2:mparam2];
mFlickr.delegate = self;
[mFlickr fetchImages];
}
}
in MTClassA.h header file mFlickr is declared as MTFlickr* mFlickr so default it it with __strong qualifier.
the callback function of fetchImages class is following
- (void)didRecieveImageLinksFromFlickr:(NSArray*)response
param1:(NSString*)param1 param2:(NSString*)param2 {
...
}
So basically I would like to know is it correct to create mFlickr objects this way in for loop and expect the callback to work correctly, if no please suggest what need to be changed ?
P.S. Do I need to change mFlickr to local variable ? If yes how should I be guaranteed that param1 and param2 methods are the one's that I've passed for teach iteration in for loop ?
You are creating multiple instances of the mFlickr object within your loop, and presumably assigning them to the same instance variable. Under ARC an assignment to an instance variable will automatically release the previous value, so your mFlickr objects are getting destroyed as soon as they are created (except the last one).
Presumably your mFlickr object is setting itself as a delegate for a URL request, it is probably this callback which is failing since the request's delegate no longer exists.
If you are creating multiple instances you should store them in an array instance variable. The callback should include a reference to the particular instance that has returned, and at this point, you remove it from the array.
You don't need to change the mFLicker to local variable. The only thing that i found in your code wrong is that, you are immediately setting mFlicker to self after initializing it. i think you must want to set the delegate of the mFlicker that you can do it by
[mFlicker setDelegate:self]
Did you set #property for mFlicker?
.h
#property(nonatomic, retain) MTFlickr *mflicker;
.m
#synthesis mflicker;
I also had similar experience, ARC was releasing my object after initialization.
so try changing your code to
self.mFlickr = [[MTFlickr alloc] initWithParam1:param1 param2:mparam2];
mFlickr.delegate = self;
[mFlickr fetchImages];
I am also not sure but i just wanted to provide some help

Syntax for accessing instance variables? (Objective-C)

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 ..].

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.

Assigning values : difference between properties and class variables?

I noticed that I rarely use properties, due to the fact that I rarely need to access my object's variables outside my class ;)
So I usually do :
NSMutableArray *myArray; // not a property !
My question is : even if i don't declare myArray as a property, does iphone make a retain anyway if I do
myArray = arrayPassedToMe;
I think so but I just wanted to confirm ;)
Any thoughts welcome !
Gotye
If you do not declare a property with 'retain' then no retain call will be made. It is generally preferable to use the property accessors (for all cases, it makes memory management much simpler), however you can perform a manual retain as such:
myArray = [otherArray retain];
Just to add to Kevin's answer, in this case you also need to make sure that any existing object at which myArray is currently pointing is freed before you assign new value to it, which means:
[myArray release];
myArray = [otherArray retain];
When you access your class variables via declared properties, all this stuff with retaining/releasing memory is done for you automatically, making your life much easier.

Should I alloc an NSMUtableArray instance variable?

This is probably a silly question but I have been thinking it over for a while with no obvious answer.
I have a small app that I have been working on and am having a problem with my NSMutableArray instance variable. It was always (null) until I added an [[NSMutableArray alloc]init] to the viewDidLoad.
I am pretty new to the Objective C world so I am trying to get an understanding of this issue. I was under the impression that with I instantiated my class the instance variables were all alloc'd. When I add items to the array without the alloc/init it remains (null) with a retain count of 0.
The array in question was declared as a (retain) property.
I can add code if this isn't clear.
Any instance variables that are objects are actually just pointers that are initialized to nil (0). That is why the item isn't retained and added to the array, since messages to nil objects return nil/0.
You need to alloc and init the object in your class's init, and then release it in the dealloc.
The retain/assign/copy qualifiers on the property declaration are about how the memory for the property value is managed in the getters and setters that the compiler synthesizes for you. (The documentation discusses them in detail, and gives example code for each kind.)
That's completely orthogonal to whether your instance variables are initialized for you or not. Declaring an ivar is just reserving storage for the value; for Objective-C classes, that's a pointer to an instance. The runtime will initialize those ivars to zero for you, but you're still responsible for creating the objects you want to store there. (The same is true in similar languages like Java or C#: declaring an Array instance variable just gives you space for a reference, it doesn't create the array for you.)