Reputation: 13346
I have a class whose sole purpose is to go download a specific file off the net, store it locally and then return the local path of the stored file.
I use this class based on whether I have a local copy of the file in question or not, and I sometimes call it up multiple times at the same time, if more than one file needs downloading. The way I use it is simply
Loader *l = [[Loader alloc] initWithDelegate:self];
[l downloadFile:someFile];
[l release];
The thing is, in order to keep it around until it's done downloading, I am actually doing [self retain];
in the class, then [self autorelease];
when it's done. This feels hacky though. How do people deal with this?
Upvotes: 1
Views: 364
Reputation: 125007
Under the circumstances, I think it's fine for your Loader to retain and autorelease itself. The most expedient solution might be to just add a detailed comment to your code that explains why it does what it does. The biggest problem is that Loader takes a delegate. Delegators don't usually retain their delegates in order to avoid retain cycles, but in this case it seems possible that the delegate could be deallocated before the Loader is finished downloading its file. If that happens, a crash is likely. So, if you want to continue with this fire-and-forget style, you might want to have Loader retain its delegate.
Upvotes: 1
Reputation: 243156
I agree that [self release]
and [self autorelease]
feel weird, but that doesn't mean they're wrong. In some situations, they can be the right thing to use (and I've used them before).
If you want to avoid them, however, you might consider making a LoaderManager
class that simply owns the Loader
objects until they're done loading stuff. It'd essentially be a wrapper around an array, and you'd use it like this (or something):
@interface LoaderManager : NSObject {
NSMutableSet *loaders;
}
@end
@implementation LoaderManager
- (id)init {
self = [super init];
if (self) {
loaders = [[NSMutableSet alloc] init];
}
return self;
}
- (void)dealloc {
[loaders release];
[super dealloc];
}
- (void)addLoader:(Loader *)loader {
[loaders addObject:loader];
}
@end
And then your Loader
object would do:
[myLoader downloadFile:someFile manager:aLoaderManager];
Which internally would simply invoke:
[aLoaderManager addLoader:self];
Upvotes: 1