I'm attaching object B via associative reference to object A. Object B observes some properties of object A through KVO.
The problem is that object B seems to be deallocated after object A, meaning its too late to remove itself as a KVO observer of object A. I know this because I'm getting NSKVODeallocateBreak exceptions, followed by EXEC_BAD_ACCESS crashes in object B's dealloc.
Does anyone know why object B is deallocated after object A with OBJC_ASSOCIATION_RETAIN? Do associated objects get released after deallocation? Do they get autoreleased? Does anyone know of a way to alter this behavior?
I'm trying to add some things to a class through categories, so I can't override any existing methods (including dealloc), and I don't particularly want to mess with swizzling. I need some way to de-associate and release object B before object A gets deallocated.
EDIT - Here is the code I'm trying to get working. If the associated objects were released prior to UIImageView being completely deallocated, this would all work. The only solution I'm seeing is to swizzle in my own dealloc method, and swizzle back the original in order to call up to it. That gets really messy though.
The point of the ZSPropertyWatcher class is that KVO requires a standard callback method, and I don't want to replace UIImageView's, in case it uses one itself.
UIImageView+Loading.h
#interface UIImageView (ZSShowLoading)
#property (nonatomic) BOOL showLoadingSpinner;
#end
UIImageView+Loading.m
#implementation UIImageView (ZSShowLoading)
#define UIIMAGEVIEW_SPINNER_TAG 862353453
static char imageWatcherKey;
static char frameWatcherKey;
- (void)zsShowSpinner:(BOOL)show {
if (show) {
UIActivityIndicatorView *spinnerView = (UIActivityIndicatorView *)[self viewWithTag:UIIMAGEVIEW_SPINNER_TAG];
if (!spinnerView) {
spinnerView = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge] autorelease];
spinnerView.tag = UIIMAGEVIEW_SPINNER_TAG;
[self addSubview:spinnerView];
[spinnerView startAnimating];
}
[spinnerView setEvenCenter:self.boundsCenter];
} else {
[[self viewWithTag:UIIMAGEVIEW_SPINNER_TAG] removeFromSuperview];
}
}
- (void)zsFrameChanged {
[self zsShowSpinner:!self.image];
}
- (void)zsImageChanged {
[self zsShowSpinner:!self.image];
}
- (BOOL)showLoadingSpinner {
ZSPropertyWatcher *imageWatcher = (ZSPropertyWatcher *)objc_getAssociatedObject(self, &imageWatcherKey);
return imageWatcher != nil;
}
- (void)setShowLoadingSpinner:(BOOL)aBool {
ZSPropertyWatcher *imageWatcher = nil;
ZSPropertyWatcher *frameWatcher = nil;
if (aBool) {
imageWatcher = [[[ZSPropertyWatcher alloc] initWithObject:self keyPath:#"image" delegate:self callback:#selector(zsImageChanged)] autorelease];
frameWatcher = [[[ZSPropertyWatcher alloc] initWithObject:self keyPath:#"frame" delegate:self callback:#selector(zsFrameChanged)] autorelease];
[self zsShowSpinner:!self.image];
} else {
// Remove the spinner
[self zsShowSpinner:NO];
}
objc_setAssociatedObject(
self,
&imageWatcherKey,
imageWatcher,
OBJC_ASSOCIATION_RETAIN
);
objc_setAssociatedObject(
self,
&frameWatcherKey,
frameWatcher,
OBJC_ASSOCIATION_RETAIN
);
}
#end
ZSPropertyWatcher.h
#interface ZSPropertyWatcher : NSObject {
id delegate;
SEL delegateCallback;
NSObject *observedObject;
NSString *keyPath;
}
#property (nonatomic, assign) id delegate;
#property (nonatomic, assign) SEL delegateCallback;
- (id)initWithObject:(NSObject *)anObject keyPath:(NSString *)aKeyPath delegate:(id)aDelegate callback:(SEL)aSelector;
#end
ZSPropertyWatcher.m
#interface ZSPropertyWatcher ()
#property (nonatomic, assign) NSObject *observedObject;
#property (nonatomic, copy) NSString *keyPath;
#end
#implementation ZSPropertyWatcher
#synthesize delegate, delegateCallback;
#synthesize observedObject, keyPath;
- (id)initWithObject:(NSObject *)anObject keyPath:(NSString *)aKeyPath delegate:(id)aDelegate callback:(SEL)aSelector {
if (!anObject || !aKeyPath) {
// pre-conditions
self = nil;
return self;
}
self = [super init];
if (self) {
observedObject = anObject;
keyPath = aKeyPath;
delegate = aDelegate;
delegateCallback = aSelector;
[observedObject addObserver:self forKeyPath:keyPath options:0 context:nil];
}
return self;
}
- (void)dealloc {
[observedObject removeObserver:self forKeyPath:keyPath];
[keyPath release];
[super dealloc];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
[self.delegate performSelector:self.delegateCallback];
}
#end
Even larger than your -dealloc issue is this:
UIKit is not KVO-compliant
No effort has been made to make UIKit classes key-value observable. If any of them are, it is entirely coincidental and is subject to break at Apple's whim. And yes, I work for Apple on the UIKit framework.
This means that you're going to have to find another way to do this, probably by changing your view layouting slightly.
The accepted answer to this related question explains the deallocation timeline of objects. The upshot is: Associated objects are released after the dealloc method of the original object has finished.
what i think is happening in your case is this:
1) object A receives the -dealloc call, after its retain count has gone to 0;
2) the association mechanism ensures that object B gets released (which is different from deallocated) at some point as a consequence.
i.e., we don't know exactly at which point, but it seems likely to me that this kind of semantic difference is the cause of object B being deallocated after object A; object A -dealloc selector cannot be aware of the association, so when the last release on it is called, -dealloc is executed, and only after that the association mechanism can send a -release to object B...
have also a look at this post.
it also states:
Now, when objectToBeDeallocated is deallocated, objectWeWantToBeReleasedWhenThatHappens will be sent a -release message automatically.
I hope this helps explaining what you are experiencing.
As to the rest, I cannot be of much help...
EDIT: just to keep on with such an interesting speculation after the comment by DougW...
I see the risk of having a sort of cyclic dependency if the association mechanism were "broken" when releasing object A (to keep going with your example).
if the association-related code were executed from the release method (instead of dealloc), for each release you would check if the "owning" object (object A) has a retain count of 1; in fact, in such case you know that decreasing its retain count would trigger dealloc, so before doing that, you would first release the associated object (object B in your example);
but what would happen in case object B were also at its turn "owning" a third object, say it C? what would happen is that at the time release is called on object B, when object B retain count is 1, C would be released;
now, consider the case that object C were "owning" the very first one of this sequence, object A. if, when receiving the release above, C had a retain count of 1, it would first try and release its associated object, which is A;
but the release count of A is still 1, so another release would be sent to B, which still has a retain count of 1; and so on, in a loop.
If you, on the other hand, send the release from the -dealloc such cyclic dependency does not seem possible.
It's pretty contrived and I am not sure that my reasoning is right, so feel free to comment on it...
objc_getAssociatedObject() for an OBJC_ASSOCIATION_RETAIN association returns an autoreleased object. Might you be calling it earlier in the same runloop cycle / autorelease pool scope as object A is deallocated? (You can probably test this quickly by changing the association to NONATOMIC).
Related
Let say i have an class named as MyTestClass.h.
Class structure is look like
#interface MyTestClass : NSObject {
NSString *testString;
}
#property (nonatomic, retain)NSString * testString;
#end
.m file
#implementation MyTestClass
#synthesize testString;
-(id) init{
[self setTestString:#""];
return self;
}
-(void)dealloc{
[self.testString release];
testString = nil;
[super dealloc];
}
#end
Now i created an object of MyTestClass and assigned testString twice
MyTestClass * myTestClass = [[MyTestClass alloc] init];
[myTestClass setTestString:#"Hi"];
[myTestClass setTestString:#"Hello"];
Now i think, two times my testStrings memory is leaked!! (one through init() and another one through my first setTestString method)
Am i correct? or will #property (nonatomic, retain) handle/release previous allocated memory?
or ,in this kind of cases ,will i need to override the setTestString() in MyTestClass.m like below code
-(void)setTestString:(NSString *)tempString{
[testString release];
testString = nil;
testString = [tempString retain];
}
Any help on this question is appreciated.
Thanks.
Any help on this question is appreciated.
I'll take this as a licence to make sone observations not necessarily directly related to your question.
Firstly, if you declare a retain property (as you have done) and synthesize it, the automatically generated getters and setters handle memory management correctly for you.
If you manually create setter (which you are allowed to do even with an #synthesize existing), you have to do the memory management yourself. Use either of trojanfoe's examples.
The setter in your question contains a bug in that if testString == tempString i.e. you assign the value of the property to itself, you could end up with assigning a dangling pointer to the property because you effectively release tempString and then retain it.
This is an implementation detail that you an safely ignore, but string literals e.g. #"blah" are compiled into the executable and will never be deallocated no matter how many times they are released. So, with your example, even if the setter did not do correct memory management, there will be no leak.
By the way, the normal pattern for an init method is
-(id) init
{
self = [super init];
if (self != nil)
{
// init stuff
}
return self;
}
or logical equivalent.
You should get into the habit of using it because you need to call the super class's init method and it is allowed to change the value of self, even to nil.
Also, while it is very good practice normally to set the object reference to nil after releasing it, in both cases when you do it, it is unnecessary. the first time, the variable is about to go out of scope and the second time you immediately assign it from some other object.
It's not a leak. Synthesized variable are correctly handled.
A synthesized method is implemented in this way (for a retain keyword)
#property (nonatomic, retain) NSString *string;
//backed by variable NSString *_string;
- (void)setString:(NSString*)newString
{
if (newString != _string) {
[_string release];
_string = [newString retain];
}
}
Of course this is a leak:
- (void)aMethod //of my class with string property
{
NSString *aString = [[NSString alloc] initWithString:#"hello"];
self.string = aString; //retain count of 2
self.string = #"hello2"; //retain count of 1 for aString
//now I don't release aString.... leak
}
If you use the auto-generated setter (in your case, setTestString:, which is also called by self.testString = ...;), the previous value of a retain property is released before being set. So no, there is no leak in the code you posted above.
The synthesized setter method should do the right thing. Here's an example of it's implementation:
- (void)setTestString:(NSString *)tempString
{
[tempString retain];
[testString release];
testString = tempString;
}
or:
- (void)setTestString:(NSString *)tempString
{
if (tempString != testString)
{
[testString release];
[tempString retain];
testString = tempString;
}
}
the dealloc is only called when the instance is destructed.
if you do :
[myTestClass setTestString:#"Hi"];
[myTestClass setTestString:#"Hello"];
in the same block, you're juste calling twice the setter. there is no memory leak.
When you use #synthesize on a property that specifies retain, the setter that's generated will handle the retain/release correctly for multiple assignments. As long as you use self. rather than going directly to the backing variable and do a final release in dealloc you should be fine.
I'm new in iPhone development and after reading Apple documentation and several posts here I still have some doubts about memory management. Please, supouse this basic class:
//MyClass.h
#interface MyClass : NSObject {
NSString *varA;
OtherClass *varB;
NSString *varC;
NSString *varD;
}
#property (nonatomic, copy) NSString *varA;
#property (nonatomic, retain) OtherClass *varB;
#property (nonatomic, copy) NSString *varC;
#property (nonatomic, copy) NSString *varD;
+ (id) initClass:(NSString *)desc;
- (void) method1:(NSString *)desc;
#end
With this implementation:
//MyClass.m
#implementation MyClass
#synthesize varA;
#synthesize varB;
#synthesize varC;
#synthesize varD;
+ (id) initClass:(NSString *)desc{
self = [super init];
if( self ){
self.varA = [NSString stringWithString:desc];
self.varB = [OtherClass initClassWithAutorelease:#"a description"]; //this class return an autoreleased object
[varB aMethod:#"something"];
}
return self;
}
- (void) dealloc{
[varB aMethod:#"something"];
[varA release];
[varB release];
[super dealloc];
}
- (void) method1:(NSString *)aString{
self.varC = aString;
self.varA = [NSString stringWithString:#"new value"];
[varB aMethod:#"something"];
}
#end
At this point what I have in mind is that the instance variables with #property have to be use without self. in the init method of the class and release them without self. in the dealloc, in other methods it is convinient to use self. for all cases. So here are my doubts:
First, I suppose that if I use self.varA= in the init method the retain counter increase so I have to release it in the dealloc method, even if the object has not been created with alloc, copy or new. Or I can use only varA= in the init and I will not need to do a release. For other class methods it's better to use the setter/getter so I can use self.varA=, ... appendString:self.varA ... or ...=self.varA without problem. Is all this correct?
Second doubt, what is best in terms of memory management and simplicity, to assign to an instance variable an object in the init method with or without autorelease? If I assign to it one without autorelease I will have to dealloc it but if I use autorelease the variable could be released before I want (like the autoreleased self.varB = [OtherClass... that will be used in the dealloc method whenever the MyClass is released).
Third, do I have to dealloc all my instance variables even if I don't use them in the init method but I could use them (read/write) in other methods of the same class? (Like varC in method1 or varD that is not used).
Fourth, do I need to take care of varA after assigning the new value in method1 if I did it well in the initClass and dealloc methods? In other words, will this generate memory leaks?
Fifth, if I declare with autorelease this class like an instance variable in a ViewController (MyClass *c; ... c = [[[MyClass alloc] initClass:#"description"] autorelease];) and I set the #property, do I have to do a release if I use it with c=... instead of self.c=...? As far as I know the behavior is the same than in my example so I should use the setter/get method in the viewDidLoad or viewWillAppear and released it in the dealloc without self..
Sixth and last one, for a instance variable is varA the same that self->varA?
Thanks...
At this point what I have in mind is that the instance variables with #property have to be use without self in the init method of the class and release them without self in the dealloc
This is completely the opposite of what is true. #property just makes the variable public outside of the class. If you have another class call that object, it will look in the header file (.h file), if it doesn't see a variable by that name, it will throw a warning during compile, and an error during runtime. When using properties with synthesize (btw, your synthesize can be all on one line, doesn't really matter though, ex: #synthesize varA, varB, varC;), using self automatically retains and keeps a retain count.
- (id) initClass:(NSString *)desc{ //Note the "-" instead of the "+" here, this is an instance method, not a class method
self = [super init];
if( self ){
[self setVarA:[NSString stringWithString:desc]];
[self setVarB:[OtherClass initClassWithAutorelease:#"a description"]];
[varB aMethod:#"something"];
}
return self;
}
in other methods it is convinient to use self for all cases.
Very untrue as well. If anything, this adds another call to the call stack and makes the execution slower (by one operation, but still, one more than needed). Consider this example:
[[self varA] doStuff:#"OMG"];
versus
[varA doStuff:#"OMG"];
The 2nd one will only access one pointer, where as the first one will have to access 2 pointers to get to the same result.
First, I suppose that if I use self.varA= in the init method the retain counter increase so I have to release it in the dealloc method, even if the object has not been created with alloc, copy or new.
Untrue. The class handles the first retain, and because of this, it handles a release as well. When your class is released, it sends a release to everything it has a retain on. If you do a release in your dealloc, this will actually decrease its retain count to -1 and create a memory error. If you set the property with self.varA = someObject, then it will give it a release when your class is dealloced. If you did self.varA = [someObject retain], then you would have to do a release in the dealloc.
Or I can use only varA= in the init and I will not need to do a release.
Kinda true, you would not need to do a release because you did not do a retain. But if something else lowers the retain count to 0 on this object, there is nothing in your class that forces the object to stay alive, and it will be freed, and if you reference it, memory error.
For other class methods it's better to use the setter/getter so I can use self.varA=, ... appendString:self.varA ... or ...=self.varA without problem. Is all this correct?
No, see why above. Only use [self setVarA:newValue] if you are changing the instance of the object, the synthesize will handle the rest. Otherwise just use [varA value] to get what ever data you need.
Second doubt, what is best in terms of memory management and simplicity, to assign to an instance variable an object in the init method with or without autorelease? If I assign to it one without autorelease I will have to dealloc it but if I use autorelease the variable could be released before I want (like the autoreleased self.varB = [OtherClass... that will be used in the dealloc method whenever the MyClass is released).
If you are creating a new object in init, autorelease it. You will have to release it in your dealloc if you do just a regular alloc init. The variable will not be released before you want it because of the retain you do on it through the property. EX
-(id) init {
self = [super init];
if(self) {
[self setVarA:[[[NSString alloc] init] autorelease]]; //Sets a new instance of NSString, autoreleased
}
return self;
}
This is correct, you do not need to do anything in your dealloc. You are creating an object with a retain count of 2 (one for the alloc you did here, and 1 for the retain you do when the synthesize sets the value in your class). Now, if it autoreleases, its retain will only go down by 1, and you will still have the retain from your property, so it will not release before your class releases
-(id) init {
self = [super init];
if(self) {
[self setVarA:[[NSString alloc] init]]; //Sets a new instance of NSString
}
return self;
}
Again, you create an object with a retain count of 2. You will need to do a [varA release] in the dealloc to knock the retain count down enough for it to be released when your class is released.
Third, do I have to dealloc all my instance variables even if I don't use them in the init method but I could use them (read/write) in other methods of the same class? (Like varC in method1 or varD that is not used).
No, you do not want to send releases to freed objects. You really should never use a dealloc in my opinion, but if you decide you want to for sure, then the worst case is to check to see if the object is null, and if its not, then release it
if(varD != null)
[[self varD] release];
Fourth, do I need to take care of varA after assigning the new value in method1 if I did it well in the initClass and dealloc methods? In other words, will this generate memory leaks?
No memory leaks from NSString. This method returns an autoreleased object. When you assign a new value to [self varA], it will release the old object, and retain the new object.
Fifth, if I declare with autorelease this class like an instance variable in a ViewController (MyClass *c; ... c = [[[MyClass alloc] initClass:#"description"] autorelease];) and I set the #property, do I have to do a release if I use it with c=... instead of self.c=...? As far as I know the behavior is the same than in my example so I should use the setter/get method in the viewDidLoad or viewWillAppear and released it in the dealloc without self..
You don't need a release in either scenario. The alloc increases the release count by 1, the autorelease will decrease it to 0. If you did self.c, that would increase it to 2, and decrease to 0 (one decrease from autorelease, and one from the property) when your class is released. You do not need to do ANYTHING in dealloc.
Sixth and last one, for a instance variable is varA the same that self->varA?
Yes, they point to the same location in memory.
when ever you write "alloc, retain, copy, new" you are responsible for releasing them in the dealloc method. ex
.h file
NSString * string;
#property (nonatomic, retain)NString * string;
.m file
#synthesize string;
-(void)dealloc{
[string release];
}
hope that helps :D
guys.i'm new to iphone.
i encounter a problem.the uiimageview can't release...here is the code.
#import <UIKit/UIKit.h>
#interface imageNavView : UIImageView {
int index;
}
#property int index;
#end
#import "imageNavView.h"
#implementation imageNavView
#synthesize index;
- (id)initWithFrame:(CGRect)frameRect{
self = [super initWithFrame:frameRect];
if (self) {
// Custom initialization.
self.userInteractionEnabled=YES;
self.multipleTouchEnabled=YES;
self.opaque=YES;
self.autoresizingMask=(UIViewAutoresizingFlexibleHeight|
UIViewAutoresizingFlexibleWidth|
UIViewAutoresizingFlexibleRightMargin
|UIViewAutoresizingFlexibleLeftMargin
|UIViewAutoresizingFlexibleTopMargin
|UIViewAutoresizingFlexibleBottomMargin);
index=0;
}
return self;
}
- (void)dealloc {
NSLog(#"before image dealloc %i",[self retainCount]);-------- log is 1
[super dealloc];
NSLog(#"after image dealloc %i",[self retainCount]);-------- log is 1,why itn't bad access?
}
#end
why does the second log NSLog(#"after image dealloc %i",[self retainCount]); is 1,not a bad access,so the imageview is not released.
i can't understand,any possible way can make this happen?...any advice will be gratefull.thanks in advance!
dealloc is a call-back method while system releases an object.
The following description is a api doc of dealloc,
Instead, an object’s dealloc method is invoked indirectly through the release NSObject protocol method (if the release message results in the receiver's retain count becoming 0).
This is an excellent example of exactly why you should never call retainCount. The absolute retain count of an object is an implementation detail and it will often be of a value that makes no sense.
The behavior of calling a method after something is deallocated is entirely undefined. In this case, it may crash, it may not. If you turned on zombie detection, it would definitely crash.
Since there is absolutely no way that retainCount could ever return 0, there is no reason for object deallocation to decrement the retain count to 0.
I wanna ask if I allocated an instance variable for private use in that class, should i release it immediately on site, or i can depend on dealloc function. (because maybe i will need it on other function) ?
//Player.h
#interface Player : NSObject
{
NSMutableArray * objectArray;
}
- (void)awake;
- (void)add;
#end
//Player.m
#implementation Player : NSObject
{
-(id) init {
self = [super init];
if (self != nil ){
[self awake];
[self add];
}
return self;
}
- (void) awake {
objectArray = [[NSMutableArray alloc] init]; //is it cause leakage?
[objectArray addObject:#"foobar"];
}
- (void) add {
[objectArray addObject:#"foobar2"];
}
- (void) dealloc {
[objectArray release];
[super dealloc];
}
}
#end
or should i using property to set the objectArray iVar?
//Player.h
#interface Player : NSObject
{
NSMutableArray * objectArray;
}
#property (nonatomic,retain)NSMutableArray* objectArray;
- (void)awake;
- (void)add;
#end
//Player.m
#implementation Player : NSObject
{
-(id) init {
self = [super init];
if (self != nil ){
[self awake];
[self add];
}
return self;
}
- (void) awake {
self.objectArray = [[NSMutableArray alloc] init autorelease]; //cause leakage?
[objectArray addObject:#"foobar"];
}
- (void) add {
[objectArray addObject:#"foobar2"];
}
- (void) dealloc {
[objectArray release];
[super dealloc];
}
}
#end
if both of them doesn't cause a leakage, what type should i use?
should i always set iVar property, and access iVar value with self even if i only want to use it in this class?
I like to take the stance that if the instance variable should not be visible outside of the class then it should not be implemented as a property. But it's a personal thing that other developers may not agree with.
Either way you would need to release the objectArray in your classes dealloc method - which is what you're currently doing.
However you need to be careful with your awake method - if it's invoked multiple times then objectArray is leaked. This is the downside of not using properties. A use of self.objectArray = [[NSMutableArray alloc] init] here would have released the previous object.
In my opinion, you should only declare properties in your header if other objects are allowed to use them. There is no good reason why you would provide an -add: method (as in your example) that adds something to your array while also providing a getter for your array so other objects can manipulate it directly. It's called encapsulation.
If you do want to have the benefits of generated getters/setters for your implementation file, you can always use a class continuation (a nameless category) inside your implementation file and include your property declarations there. That way you get real, auto-generated properties that are only visible to your class' implementation.
Personally, I wouldn't use any getter or setter methods in your example. Just allocate the NSArray in your -init and release it in -dealloc. If this -awake method of yours might be called multiple times, just add an [objectArray removeAllObjects] call and you're sure to have an empty array without worrying about memory management.
It is very likely that memory will leak in your first example because you are not sending release to the previously set instance variable (if it already existed).
This is why you should use property setters - they handle all of this stuff for you.
Also, since you are obtaining ownership of the instance variable through the property (which is defined with the retain keyword), you will definitely leak memory if you don't send the instance variable the -release message in your -dealloc method.
So the verdict is that you should use the second example, not the first.
Is there a reason, other than as may be required by object scope across different methods of the object, to use an object like this:
#interface
...
ViewMgmtAppDelegate : NSObject <UIApplicationDelegate> {
Obj *obj1;
...
}
#end
#implementation
- (void)applicationDidFinishLaunching:(UIApplication *)application {
obj1 = [Obj alloc];
[window addSubview:obj1];
...
}
- (void)dealloc {
[obj1 release];
...
}
#end
Instead of this:
#interface
...
ViewMgmtAppDelegate : NSObject <UIApplicationDelegate> {
...
}
#end
#implementation
- (void)applicationDidFinishLaunching:(UIApplication *)application {
Obj obj1 = [Obj alloc];
[window addSubview:obj1];
[obj1 release];
...
}
- (void)dealloc {
...
}
#end
Is either way more efficient?
Any help appreciated // :)
I assume you are asking if you should release the object right after addSubview or in dealloc.
It depends on the application logic and what addSubview does. If addSubview retains the object you can release it right after the call if you don't need it in your other object.
When window is done with it and it releases the object which will get deallocated if no other object holds reference to it.
If on the other hand you keep the reference until your object is deallocated then the object will hang around until your object is deallocated.
If you don't need it then release right away.
By the way the correct way to create and instance is to call:
Obj * o = [[Object alloc] init]
Alloc allocates memory, init (or any other init... methods) initializes the object (I believe).
You would use your first example in case that your obj1 will be used after the view finished loading. For example after a click event.
The second example will be used if this is not the case. So Obj1 is not needed anymore after the release and does not need to use the RAM of the iPhone.
If the object is only used by that method, then it should be a local variable and released in that method (as in the second example). If it's a property of the class that other methods use, it should be stored in an instance variable and released when the owning object goes away (as in the first example).