问题
I am making an OpenSource (github) helper class for downloading images asynchronously (I had major trouble with).
However, I have delegate methods set up to alert the delegate that a image has finished downloading. The problem is that the delegate method is not getting called. I am setting the delegate and everything, but I don't have a clue why the problem is occurring.
Please take a look at my code! I have only posted the relevant code.
MKAsyncImageDownloader.h
@protocol MKAsyncImageDownloaderDelegate <NSObject>
@required
- (void)imageShouldFinishDownloading;
@end
@interface MKAsyncImageDownloader : NSObject {
id <MKAsyncImageDownloaderDelegate> delegate;
}
- (id) initWithDelegate:(id <MKAsyncImageDownloaderDelegate>) delegat;
@property (retain, nonatomic) id <MKAsyncImageDownloaderDelegate> delegate;
@end
MKAsyncImageDownloader.m
- (id) initWithDelegate:(id<MKAsyncImageDownloaderDelegate>) delegat {
self = [super init];
if (self) {
delegate = delegat;
}
return self;
}
- (void)imageAtURLHasDownloaded:(NSDictionary *)dict {
[downloadedImageArray addObject:[dict objectForKey:@"image"]];
[[self delegate] imageShouldFinishDownloading];
}
MKOperation.m Subclass of NSOperation. I alloc/init MKAsynImageDownloader to perform the selector only. Code:
- (void)start {
UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:self.targetURL]];
if (image) {
NSDictionary *dict = [[NSDictionary alloc] initWithObjects:[NSArray arrayWithObjects:image, self.targetURL, nil] forKeys:[NSArray arrayWithObjects:@"image", @"url", nil]];
MKAsyncImageDownloader *downloader = [[MKAsyncImageDownloader alloc] init];
[downloader performSelectorOnMainThread:@selector(imageAtURLHasDownloaded:) withObject:dict waitUntilDone:YES];
[dict release];
[downloader release];
}
[image release];
}
RootViewController.h
MKAsyncImageDownloader *loader;
RootViewController.m Just to show how I am setting the delegate.
loader = [[MKAsyncImageDownloader alloc] initWithDelegate:self];
回答1:
In your start
method you are never calling your proper init method, you are calling:
MKAsyncImageDownloader *downloader = [[MKAsyncImageDownloader alloc] init];
you should be calling
MKAsyncImageDownloader *downloader = [[MKAsyncImageDownloader alloc] initWithDelegate:myDelegate];
Then you say you set a loader
object somewhere else? These are two separate objects, the one you actually seem to use is what is referenced above.
That is:
loader = [[MKAsyncImageDownloader alloc] initWithDelegate:self];
does not make
MKAsyncImageDownloader *downloader = [[MKAsyncImageDownloader alloc] init];
work. Your MKOperation has no reference to your loader
class that has the delegate set.
You state:
MKOperation.m Subclass of NSOperation. I alloc/init MKAsynImageDownloader to perform the selector only.
I think you misunderstand what you are doing here. You are create a brand new instance of MKAsynImageDownloader
and performing the selector on that instance, not the loader
instance that lives in your RootController. You probably want to have MKOperation
take a MKAsyncImageDownloader
object during it init.
EDIT:
This is the "downloader" I'm referring to. In your MKOperation's start
if (image) {
NSDictionary *dict = [[NSDictionary alloc] initWithObjects:[NSArray arrayWithObjects:image, self.targetURL, nil] forKeys:[NSArray arrayWithObjects:@"image", @"url", nil]];
-->> MKAsyncImageDownloader *downloader = [[MKAsyncImageDownloader alloc] init];
[downloader performSelectorOnMainThread:@selector(imageAtURLHasDownloaded:) withObject:dict waitUntilDone:YES];
[dict release];
[downloader release];
}
That is the separate instance from the one that lives in your RootViewController, this one does not have a delegate set. THIS is the one you are doing work on, therefore, this one is the one attempting to notify the delegate... but again, it doesn't have a delegate set.
回答2:
Have you looked into SDWebImage?
Sometimes the easiest way to solve a problem is to use working code you don't have to maintain...
https://github.com/rs/SDWebImage
来源:https://stackoverflow.com/questions/5784850/delegate-method-not-being-called