How to tell if an object has already been allocated, so it isn't allocated multiple times? - iphone

Please be nice.. I am a noob with this stuff. I want to allocate and use an object through a method that I call many times, and instead of making it a global variable and allocating it in my initWithFrame method I want to alloc it in just the one method, and make it a local variable that I allocate then and use then.

You need to step back and think about how many different things need to access said object.
If it is everyone, then you should likely implement the shared instance pattern. Something like:
+ (MyObject *) mySharedObjectThatEveryoneUses
{
static MyObject *sharedInstance;
if (!sharedInstance) {
sharedInstance = [MyObject alloc];
sharedInstance = [sharedInstance init];
}
return sharedInstance;
}
Note that the above does not account for threading on initialization. I.e. if multiple threads simultaneously call the method for the first time, you might end up with multiple instances. Also note that the splitting of +alloc and -init is a pattern that is unique to this situation. Doing so avoids the situation where the -init method causes + mySharedObjectThatEveryoneUses to be invoked, creating a second instance before the assignment can happen.
Now, if you are talking about access within an object graph; access to the single instance within some subset of objects in your application, then you will need to have an instance variable somewhere that all of the objects can get to.
For example, say you are implementing a game where there is a Player object and that Player object has a bunch of Piece instances. When a Piece is created, you would typically have a property that refers to the owning player and that would be your single point of reference.
If you need something more transient, you should likely look to what should be your controller layer. I.e. there has to be some object somewhere that can act as a coordinator for the set of objects that need access to that single instance.

If I understood your question correctly, you're looking for a static variable. A static variable keeps its value like a global variable, but it "lives inside" a function like a local variable. Your function could look something like this:
+ (MyObject *)getSingletonObject {
static MyObject *obj = [[MyObject alloc] init];
return obj;
}
obj would be created the first time you called this method, but calling the method again would return the same object it had already created.

What you want is called a Singleton. You can read up on Apple's recommended way to create singletons here:
http://developer.apple.com/Mac/library/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html#//apple_ref/doc/uid/TP40002974-CH4-SW32
Look for "Creating a Singleton Instance" in the "Cocoa Objects" section. There are a few more methods it's good to define beyond just a class level initializer.

I'm not entirely sure I understand your question, but you can't really allocate the same object many times.
Each time you want a new instance, you ask the Class object to allocate a new instance for you (yes, classes being objects themselves is mind blowing). So this code:
NSString* s;
s = [[NSString alloc] init];
s = [[NSString alloc] init];
Here you are creating two instances of NSString. This code is bad because we have alloc'd the first instance and have not released, and assigned its only reference (s) to a new instance. This would cause a memory leak.

Related

How to check what class was an object initialized in Objective C

Is it possible to check and get the name of the class an object was initialized in?
Example: I have Class A. I created object ABObject using [[ABOBject alloc] init]; via an instance method.
How can I find out the class from which an instance ABObject was created, namely "A" here?
Objects can be created outside the context of a class, so it wouldn't make sense for this to be a built-in language feature.
If you do have to do this, one way to work around it would be to use the objc_setAssociatedObjects() function in objc/runtime.h immediately after any such object was instantiated. Something like:
ABObject *object = [[ABObject alloc] init];
objc_setAssociatedObject(object, #"InstantiatingClassKey", [self class], OBJC_ASSOCIATION_ASSIGN);
Then you could get it with objc_getAssociatedObject(object, #"InstantiatingClassKey").
I think you'd be better off re-assessing your design because this is not going to be particularly maintainable. Even extracting this into a category on NSObject to remove duplicated code you'll still have an extra step to remember and weird relationships between your objects.
Also, as Martin R. points out in the comments, I'm taking a shortcut and passing a string literal as the key argument for the function, in reality you'd want to follow the practice of using the address of some static or global variable.

When to use properties and allocation initializing

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

How to initialize custom classes in ViewControllers?

I'm still trying to wrap my head around how to best create and init custom classes in several ViewControllers.
Let's say I create a MyData class.
In FirstViewController, I wish to initialize it.
From one of the iPhone classes at college, a teacher suggested to use the following so that several instances of the same object are not created.
#property and #synthesize myData is done
-(MyData *)myData {
if (!myData) {
myData = [[MyData alloc] init];
}
return myData;
}
myData is released
Three things with this. If I put a MyData alloc init in one of the FirstViewController's methods, then I'm told every time that method is called, a new object is created which is consuming memory and is a potential for memory leaks. By creating the above getter, every time the object is used, the getter is called which seems like a waste of CPU cycles. If I don't do an alloc init, then the object is not created at all.
Lastly in subsequent views, I find I can get by just doing #property and #synthesize MyData in SecondViewController and then pass the myData object in the FirstViewController to it.
So why do I need alloc init to create the object in FirstVC and not in the SecondVC? Shouldn't I need to do that to allocate some memory for the object to be created so I can send in the reference?
Is there a better way of alloc init the object myData in the FirstVC that doesn't create multiple instances yet doesn't unnecessarily waste CPU cycles? (For those thinking CPU is cheap, what if you had many objects declared and think mobile)
Hope this makes sense. Thanks in advance,
Hiren.
I'm not sure I can fully resolve your confusion, but here are a few ideas to consider:
First, don't worry about the load on the CPU associated with using property accessors. If that's where your bottleneck is, either you're doing very well or your app isn't doing very much. It's great to be conscious of potential performance issues; it's not so great to fix them before you know that there's really a problem.
Second, why not just initialize your properties in your -initWithNibName:bundle: method? Like this:
-(id)initWithNibName:(NSString*)name bundle:(NSString*)bundle
{
if (self = [super initWithNibName:name bundle:bundle]) {
myData = [[MyData alloc] init];
}
return self;
}
The code you showed looks a bit like what one might use to create a singleton, i.e. a class that can only be instantiated once. Could that be what your teacher was talking about? It's not something you need to do most of the time.
I'm not sure how to address your issue with the second view controller... I think there's some more confusion there, and since we don't have any code to talk about, it's hard to proceed. If you're using the "modern" Objective-C runtime, you can declare properties without providing matching instance variables, and perhaps that's what you're doing, but you still need to initialize your properties before you use them.

iPhone Memory Management

There are a few concepts about iPhone memory management that have got me confused, so I was hoping that someone could clarify these.
(a) Say that I am calling a function which returns an image, and I want to store that returned image in a variable so that I can assign it to various other variables without having to re-call the image generation function each time. At the moment I am doing the following:
UIImage *storedImage = [someFunction returnImage];
and because the storedImage is not alloc'ed I am not releasing the variable.
However, should I be explicitly alloc'ing and releasing the UIImage instead?
UIImage *storedImage = [[UIImage alloc] init];
storedImage = [someFunction returnImage];
...do stuff...
[storedImage release];
What is the implication of doing the direct assignment without alloc rather than alloc'ing the variable and then assigning?
(b) In the init method for various classes I am setting up the instance variables. At the moment I am doing the following:
self.arrayVariable = [[NSMutableArray alloc] init];
However, I have seen others do the assignment this way:
theArrayVariable = [[NSMutableArray alloc] init];
self.arrayVariable = theArrayVariable;
[theArrayVariable release];
or
theArrayVariable = [[NSMutableArray alloc] init];
arrayVariable = theArrayVariable;
[theArrayVariable release];
...which is the same as above, but without the self.
What is the difference between the three methods and which is better to use?
Regarding returning objects from methods, you should always return an autoreleased object from any method which does not begin with the name alloc, new, or contains copy. This is defined in Apple's object ownership policy, which states that you own any object that you create ("create" is defined as an object which you sent retain to, or used any of the aforementioned messages to retrieve an object), and that you are responsible for relinquishing ownership of that object by sending it the release or autorelease message.
The first method using self uses the property setter to set the instance variable to the argument (in this case whatever is on the RHS of the assignment).
This will do whatever you specified in your #property declaration (for example if you specified retain, the setter will retain the new value and release the old value).
The second method sets up a pointer to an NSMutableArray and passes it off to your property setter via self, which will most likely retain it, thereby bringing the reference count up to 2, since the object was previously alloc-ed, so you need to release it after this line to bring it back down to 1.
The third method will not work, because you are releasing an object with a reference count of 1 at the point of invoking release. How so you ask? Well, the first line sets up a pointer to an alloc-ed object, then directly assigns it to your instance variable, which will just point the ivar to the same object that theArrayVariable is pointing to. Then, that same object that theArrayVariable is pointing to gets sent the release method, which will effectively bring down the reference count of your ivar as well as the receiver, to 0. At this point both your instance variable and theArrayVariable will get deallocated.
a) The general rule for objective-c is that if you alloc it you must release it. In the first example, the method is returning a pointer to an object that already exists, and therefore you are not responsible for releasing it. In the second example, the first like is pointless since you aren't using allocated memory for stored image. This may cause a memory leak.
b) The first two are just stylistic differences, with no difference in outcome. In those, you will be left with arrayVariable pointing to the object returned by [[NSMutableArray alloc] init]; (assuming you have retain in the #property declaration) and you should release it in the -dealloc method. As stated above, the third will not work because you are merely passing off the pointer.
Here is a useful article for understanding obj-c memory management: http://memo.tv/memory_management_with_objective_c_cocoa_iphone
a) The code you gave does not do what you want. When you say
UIImage *storedImage = [someFunction returnImage];
someFunction returns an image object to you, but it does not guarantee that the image object will live forever. If you do not want the image to be freed without your permission in a future time, you should own it by calling retain like this:
UIImage *storedImage = [[someFunction returnImage] retain];
So now, this image object is owned by both someFunction and you. When you finish your work with this object you release it by calling release. When both someFunction and you call release for this object, it will be released (Of course if it is not owned by another owner).
In the other code segment, you create an image object and own it by calling
UIImage *storedImage = [[UIImage alloc] init];
But then you lose its reference by assigning a new object to the storedImage pointer by calling someFunction. In this situation the image created by you is not freed but continues to live somewhere in the memory.

Would it be correct/ellegant use only alloc without init?

If we don't want to implement init method in our class, and bearing in mind that init in NSObject only returns an instance of the object without initialization, I don't see the point of calling init if we already get the instance with alloc. I have tried and it works, but I am not sure it won't cause future problems.
myClass *newObject = [myClass alloc];
instead of:
myClass *newObject = [[myClass alloc] init];
Thanks a lot.
No, just calling alloc would not be correct. alloc zeroes out all instance variables of the object, init then has the chance to set all or some instance variables to their default values. Some classes even use their init methods to create another instance and return that one instead of the one you allocated.
Many classes expect that their init methods get called and would possibly cause crashes if you don't call init. If you are talking about a custom class that inherits directly from NSObject and needs no initialization of instance variables, you might get away with [myClass alloc] but it is definitely not good programming style.
I think that it is not a good idea.
Read Cocoa Design Pattern, especially the "Two stage creation"
You can also read this article http://www.informit.com/articles/article.aspx?p=1398610
I think that it wouldn't matter much if you didn't implement a "- (id)init" because if you did, you would call NSObject's init method which just returns the same value you send to the method. Though it is a good idea to create your own init method to set your instance variable.
in runtime source code
perform -(id)init will call _objc_rootInit(self) and will return self. I guess only perform init is OK。