iOS MAKImageGalleryView 使用 AFNetworking/AFImageDownloader 下载照片
iOS MAKImageGalleryView downloading photos using AFNetworking/AFImageDownloader
我正在尝试根据 MAKImageGalleryView, but I need download images from server, so I use AFImageDownloader
(AFNetworking).
创建照片库
根据MAKImageGalleryView
的文档,我必须实现这个方法:
MAKImageGalleryView.h
- (void)loadImageInGallery:(MAKImageGalleryView *)galleryView atIndex:(NSInteger)index callback:(void(^)(UIImage *))callback;
MAKImageGalleryView.m
#import "MAKImageGalleryView.h"
- (void)loadImageForRow:(NSInteger)row withBlockToCell:(MAKImageGalleryViewImageCell *)cell {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSUInteger key = random();
cell.blockLoadingId = key;
[self.imageGalleryDataSource loadImageInGallery:self atIndex:row callback:^(UIImage *image) {
if (cell.blockLoadingId == key) {
dispatch_async(dispatch_get_main_queue(), ^{
if (cell.blockLoadingId == key) { //if still not reused
cell.image = image;
}
});
}
}];
});
}
所以我创建了类似的东西:
ViewController.m
- (void)loadImageInGallery:(MAKImageGalleryView *)galleryView atIndex:(NSInteger)index callback:(void(^)(UIImage *))callback{
NSString * imageName = [NSString stringWithFormat:@"http://example.com/image%i.jpg", index];
AFImageDownloader* download = [[AFImageDownloader alloc] init];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString: imageUrl] cachePolicy:NSURLRequestReturnCacheDataElseLoad
timeoutInterval:60];
[download downloadImageForURLRequest:request success:^(NSURLRequest * request, NSHTTPURLResponse * response, UIImage * image) {
NSLog(@"Success download image");
callback(image);
} failure:^(NSURLRequest * request, NSHTTPURLResponse * response, NSError * error) {
NSLog(@"Error download image");
}];
结果:
时不时会看到一些照片,而另一些却看不到。
通过使用注释进行调试,似乎需要保留 AFImageDownloader
直到操作完成。如果不是,那么下载器很有可能会过早发布并自动终止下载。
您需要保留您的下载器。最直接的解决方案是使用强 属性 并将您的调用修改为:
- (void)loadImageInGallery:(MAKImageGalleryView *)galleryView atIndex:(NSInteger)index callback:(void(^)(UIImage *))callback{
NSString * imageName = [NSString stringWithFormat:@"http://example.com/image%i.jpg", index];
AFImageDownloader* download = [[AFImageDownloader alloc] init];
self.currentDownloader = download;
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString: imageUrl] cachePolicy:NSURLRequestReturnCacheDataElseLoad
timeoutInterval:60];
...
如果您有多个下载器,那么您需要将它们添加到数组中,但也需要将它们删除:
- (void)loadImageInGallery:(MAKImageGalleryView *)galleryView atIndex:(NSInteger)index callback:(void(^)(UIImage *))callback{
NSString * imageName = [NSString stringWithFormat:@"http://example.com/image%i.jpg", index];
AFImageDownloader* download = [[AFImageDownloader alloc] init];
[self.currentDownloaders addObject: download];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString: imageUrl] cachePolicy:NSURLRequestReturnCacheDataElseLoad
timeoutInterval:60];
[download downloadImageForURLRequest:request success:^(NSURLRequest * request, NSHTTPURLResponse * response, UIImage * image) {
NSLog(@"Success download image");
[self.currentDownloaders removeObject: download];
callback(image);
} failure:^(NSURLRequest * request, NSHTTPURLResponse * response, NSError * error) {
NSLog(@"Error download image");
[self.currentDownloaders removeObject: download];
}];
或者就像我们在测试中所做的那样,您可以简单地让块保留下载:
只需在任何块内调用 NSLog(@"Success download image %@", download);
即可强制块保留 download
。只要保留块,下载就会保留。至少在其中一个块被调用之前是这样。
这是最干净的过程,但由于该对象不是您创建的,您需要检查这些对象是否在某个时候被释放。如果它们没有正确完成,那么这段代码将产生一个保留周期并随之产生内存泄漏。
因此,在您使用最后一个程序之前,请检查以下内容:
子类 AFImageDownloader
,覆盖 dealloc
并打印类似 NSLog(@"Did deallocate");
的内容,并使用此子类代替您的 AFImageDownloader
。如果您在某个时候看到日志 "Did deallocate",那么使用 "log trick" 是安全的。如果不是那么你不应该使用这个过程,因为它会产生内存泄漏!!!
我正在尝试根据 MAKImageGalleryView, but I need download images from server, so I use AFImageDownloader
(AFNetworking).
根据MAKImageGalleryView
的文档,我必须实现这个方法:
MAKImageGalleryView.h
- (void)loadImageInGallery:(MAKImageGalleryView *)galleryView atIndex:(NSInteger)index callback:(void(^)(UIImage *))callback;
MAKImageGalleryView.m
#import "MAKImageGalleryView.h"
- (void)loadImageForRow:(NSInteger)row withBlockToCell:(MAKImageGalleryViewImageCell *)cell {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSUInteger key = random();
cell.blockLoadingId = key;
[self.imageGalleryDataSource loadImageInGallery:self atIndex:row callback:^(UIImage *image) {
if (cell.blockLoadingId == key) {
dispatch_async(dispatch_get_main_queue(), ^{
if (cell.blockLoadingId == key) { //if still not reused
cell.image = image;
}
});
}
}];
});
}
所以我创建了类似的东西:
ViewController.m
- (void)loadImageInGallery:(MAKImageGalleryView *)galleryView atIndex:(NSInteger)index callback:(void(^)(UIImage *))callback{
NSString * imageName = [NSString stringWithFormat:@"http://example.com/image%i.jpg", index];
AFImageDownloader* download = [[AFImageDownloader alloc] init];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString: imageUrl] cachePolicy:NSURLRequestReturnCacheDataElseLoad
timeoutInterval:60];
[download downloadImageForURLRequest:request success:^(NSURLRequest * request, NSHTTPURLResponse * response, UIImage * image) {
NSLog(@"Success download image");
callback(image);
} failure:^(NSURLRequest * request, NSHTTPURLResponse * response, NSError * error) {
NSLog(@"Error download image");
}];
结果: 时不时会看到一些照片,而另一些却看不到。
通过使用注释进行调试,似乎需要保留 AFImageDownloader
直到操作完成。如果不是,那么下载器很有可能会过早发布并自动终止下载。
您需要保留您的下载器。最直接的解决方案是使用强 属性 并将您的调用修改为:
- (void)loadImageInGallery:(MAKImageGalleryView *)galleryView atIndex:(NSInteger)index callback:(void(^)(UIImage *))callback{
NSString * imageName = [NSString stringWithFormat:@"http://example.com/image%i.jpg", index];
AFImageDownloader* download = [[AFImageDownloader alloc] init];
self.currentDownloader = download;
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString: imageUrl] cachePolicy:NSURLRequestReturnCacheDataElseLoad
timeoutInterval:60];
...
如果您有多个下载器,那么您需要将它们添加到数组中,但也需要将它们删除:
- (void)loadImageInGallery:(MAKImageGalleryView *)galleryView atIndex:(NSInteger)index callback:(void(^)(UIImage *))callback{
NSString * imageName = [NSString stringWithFormat:@"http://example.com/image%i.jpg", index];
AFImageDownloader* download = [[AFImageDownloader alloc] init];
[self.currentDownloaders addObject: download];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString: imageUrl] cachePolicy:NSURLRequestReturnCacheDataElseLoad
timeoutInterval:60];
[download downloadImageForURLRequest:request success:^(NSURLRequest * request, NSHTTPURLResponse * response, UIImage * image) {
NSLog(@"Success download image");
[self.currentDownloaders removeObject: download];
callback(image);
} failure:^(NSURLRequest * request, NSHTTPURLResponse * response, NSError * error) {
NSLog(@"Error download image");
[self.currentDownloaders removeObject: download];
}];
或者就像我们在测试中所做的那样,您可以简单地让块保留下载:
只需在任何块内调用 NSLog(@"Success download image %@", download);
即可强制块保留 download
。只要保留块,下载就会保留。至少在其中一个块被调用之前是这样。
这是最干净的过程,但由于该对象不是您创建的,您需要检查这些对象是否在某个时候被释放。如果它们没有正确完成,那么这段代码将产生一个保留周期并随之产生内存泄漏。
因此,在您使用最后一个程序之前,请检查以下内容:
子类 AFImageDownloader
,覆盖 dealloc
并打印类似 NSLog(@"Did deallocate");
的内容,并使用此子类代替您的 AFImageDownloader
。如果您在某个时候看到日志 "Did deallocate",那么使用 "log trick" 是安全的。如果不是那么你不应该使用这个过程,因为它会产生内存泄漏!!!