Advertise Mobile SDKs Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

Interface 2, Advanced iOS
Mockup & Code Gen
($9.99)

Make your own iPhone apps
and run them live!
(free)

Pic Frame Dynamo: Photo Editing
($0.99)

Abiliator
($1.99)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Development

Reply
 
LinkBack Thread Tools Display Modes
Old 10-22-2010, 02:19 AM   #1 (permalink)
Registered Member
 
Join Date: Jul 2010
Posts: 42
frankmail007 is on a distinguished road
Default Design problem - Release an object in its delegate method

I have some problem to design my program which need to release an object in its delegate method. My main class (View controller in my case) holds a lot of tasks ( which represented by Task class) in a NSMutableDictionary. When task ends, it will call its delegate method in main class. Then the Task object will be remove from NSMutableDictionary. The reason why I remove the Task object in the delegate method is because I need to add/remove Task object dynamically. The problem is after I remove the Task object from NSMutableDictionary, it'll be released. But it has to return to the place of Task object call the delegate method. At this point, the Task object has been release already. It of course will cause crash.

Please refer to my code, it will explain my situation more clearly:
Code:
//////// main class (view controller)
	_allTasks = [[NSMutableDictionary alloc]init];
	
	// You have to make sure the task name unique
	Task* task1 = [[Task alloc]initWithDelay:10];
	task1.name = @"Task1";
	task1.delegate = self;
	[_allTasks setObject:task1 forKey:task1.name];
	[task1 start];
	[task1 release];

-(void)onTaskFinished:(Task*)task
{
	[_allTasks removeObjectForKey:task.name];
}

//// Task.h
#import <Foundation/Foundation.h>

@class Task;
@protocol TaskDelegate <NSObject>

-(void)onTaskFinished:(Task*)task;

@end

@interface Task : NSObject {

	id<TaskDelegate>	_delegate;
	NSUInteger			_delay;
	NSString*			_name;
	
}

@property (nonatomic,assign) id delegate;
@property (nonatomic,retain) NSString* name;

-(id)initWithDelay:(NSUInteger)second;
-(void)start;

@end

/////// Task.m ///////////
#import "Task.h"

@implementation Task

@synthesize delegate = _delegate;
@synthesize name = _name;

-(id)initWithDelay:(NSUInteger)second
{
	if ( self == [super init] )
	{
		_delay = second;
	}
	return self;
}

-(void)start
{
	[NSTimer scheduledTimerWithTimeInterval:_delay target:self selector:@selector(onTimer:) userInfo:nil repeats:0];
	[self release];
}

-(void)onTimer:(NSTimer*)theTimer
{
	[theTimer invalidate];
	
	[_delegate performSelector:@selector(onTaskFinished:) withObject:self];
}

-(void)dealloc
{
	[super dealloc];
	self.delegate = nil;
	[self.name release];
}

@end
Please note, there is a [self release] in my start method. That is I purposely added to mimic my real situation (the [NSTimer scheduledTimerWithTimeInterval] will increase my retain count probably because of the target parameter.

Can anybody advise what I should to handle this kind of problem? Thank you so much

Last edited by frankmail007; 10-22-2010 at 02:23 AM.
frankmail007 is offline   Reply With Quote
Old 10-22-2010, 02:34 AM   #2 (permalink)
Pro. Game Developer
iPhone Dev SDK Supporter
 
Join Date: Feb 2009
Location: żLa Islas Hermosas?
Posts: 2,176
Kalimba is on a distinguished road
Default

What if you did something like this (my added code in RED):
Code:
-(void)onTimer:(NSTimer*)theTimer
{
	[theTimer invalidate];
	
	[self retain];
	[_delegate performSelector:@selector(onTaskFinished:) withObject:self];
	[self autorelease];
}
Essentially, you increase the retain count prior to calling that code that was deallocating the object (which will prevent it from dealloc'ing). Then, when you return, you put the object into the autorelease pool and let it eventually dealloc the object.
__________________
~~ Word Flurry ~~ App Store / Website / Facebook
Kalimba is offline   Reply With Quote
Old 10-22-2010, 02:51 AM   #3 (permalink)
Registered Member
 
Join Date: Jul 2010
Posts: 42
frankmail007 is on a distinguished road
Default

Quote:
Originally Posted by Kalimba View Post
What if you did something like this (my added code in RED):
Code:
-(void)onTimer:(NSTimer*)theTimer
{
	[theTimer invalidate];
	
	[self retain];
	[_delegate performSelector:@selector(onTaskFinished:) withObject:self];
	[self autorelease];
}
Essentially, you increase the retain count prior to calling that code that was deallocating the object (which will prevent it from dealloc'ing). Then, when you return, you put the object into the autorelease pool and let it eventually dealloc the object.
Thanks. I think it should work. Smart solution.
frankmail007 is offline   Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



» Advertisements
» Online Users: 331
11 members and 320 guests
condor304, Desert Diva, Domele, dre, dreamdash3, mottdog, oceanlablight, palme2elie, Paul Slocum, schmallegory
Most users ever online was 1,387, 04-10-2012 at 04:21 AM.
» Stats
Members: 175,659
Threads: 94,118
Posts: 402,895
Top Poster: BrianSlick (7,990)
Welcome to our newest member, dreamdash3
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 01:15 AM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0