https://github.com/mwaterfall/MWPhotoBrowser一个可选的网格视图简单的iOS照片浏览器,标题和选择。MWPhotoBrowser可以通过提供UIImage对象显示一个或多个图像,或URL的Web图像文件,或图书馆资产。照片处理下载和缓存浏览器从Web照片无缝。照片可以放大和平移,和可选的标题可以显示(可定制。浏览器也可以用于允许用户选择一个或更多的照片可以使用网格或主视图。
单张图片浏览分析,先上图大体上分为三个部分,分开介绍。
1.1、主题图片部分。模型类:MWPhoto,遵守MWPhoto协议,用户可以继承这个类添加更多的图片信息,或者自定义模型类,前提是继承上述的协议。我们首先看下MWPhoto协议,这里面定义了什么方法:两个通知名称:MWPHOTO_LOADING_DID_END_NOTIFICATION @“MWPHOTO_LOADING_DID_END_NOTIFICATION" 和MWPHOTO_PROGRESS_NOTIFICATION @“MWPHOTO_PROGRESS_NOTIFICATION”见名知意,是图片加载完毕和图片加载中的通知,用于处理进度条等信息。必要的属性和方法:@property (nonatomic, strong) UIImage *underlyingImage;主要的图片,一个model对应一个图片- (void)loadUnderlyingImageAndNotify;加载图片并发出通知,当浏览器检测到图片没有加载进内存但是需要的时候,调用这个方法- (void)performLoadUnderlyingImageAndNotify;从资源中获取图片信息并且完成之后发出通知。必须异步加载图片,推荐使用SDWebImageDecoder来压缩图片。可选的属性和方法BOOL emptyImage;图片是否为空,当照片是空的时候,不展示加载错误提示框BOOL isVideo;是否是视频资源- (void)getVideoURL:(void (^)(NSURL *url))completion;获取视频URL支持完成回调- (NSString *)caption;图片描述信息,nil表示没有图片描述信息- (void)cancelAnyLoading;取消后台的加载。总结:通过上述的属性和方法,可以总体上了解一个图片模型可以做什么操作,如果需要自定义的话,需要怎么处理。把这里包括图片,描述,是否为空,是否是视频;操作包括加载、下载、压缩、取消等。接下来看模型类MWPhoto内部的实现,这里不一一介绍,我们关注几个重要的地方,抛砖引玉。模型类的头文件提供了初始化方法以及便利构造器,属性接口有:描述、视频URL、是否是空图片、时候是视频。.m文件中定义了几个私有属性:BOOL _loadingInProgress;标识资源正在加载中,加载完毕置为NOid_webImageOperation;记录下图片的下载操作,方便停止取消
PHImageRequestID _assetRequestID;这个类是系统提供的图片处理的接口,用于存放图片请求ID,在停止加载的时候使用;
PHImageRequestID _assetVideoRequestID;视频请求ID
UIImage *image; 图片
UIImage *image; 图片URL
PHAsset *asset;资源包
assetTargetSize; 图片尺寸
获取视频URL
- (void)getVideoURL:(void (^)(NSURL *url))completion {
if (_videoURL) { // 已经获取了URL直接回传
completion(_videoURL);
} else if (_asset && _asset.mediaType == PHAssetMediaTypeVideo) {
// 查看资源文件是否存在并且是视频资源
[self cancelVideoRequest]; // 停止处理中的请求
PHVideoRequestOptions *options = [PHVideoRequestOptions new];
options.networkAccessAllowed = YES;
typeof(self) __weak weakSelf = self;// weak属性防止循环引用
_assetVideoRequestID = [[PHImageManager defaultManager] requestAVAssetForVideo:_asset options:options resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info) {
typeof(self) strongSelf = weakSelf; // 内部定义成strong防止self在block内部释放掉AFN也是这样处理的。
if (!strongSelf) return;
strongSelf->_assetVideoRequestID = PHInvalidImageRequestID;
if ([asset isKindOfClass:[AVURLAsset class]]) {
completion(((AVURLAsset *)asset).URL);// 获取视频URL回传
} else {
completion(nil);
}
}];
}
}
加载图片并且发送通知:作者根据图片资源的不同来进行不同的处理,系统资源库、本体图片或者是来自网络的图片
从网络加载图片:使用SDWebImageManager下载图片。
从本地加载(这里的本地值得是沙盒中):imageWithContentsOfFile:
从资源库(也就是我们的照片):异步加载,
ALAssetsLibrary *assetslibrary = [[ALAssetsLibrary alloc] init];
[assetslibrary assetForURL:url resultBlock:^(ALAsset *asset){
ALAssetRepresentation *rep = [asset defaultRepresentation];
CGImageRef iref = [rep fullScreenImage];
if (iref) {
self.underlyingImage = [UIImage imageWithCGImage:iref];
}
[self performSelectorOnMainThread:@selector(imageLoadingComplete) withObject:nil waitUntilDone:NO];// 在主线程更新图片
}
failureBlock:^(NSError *error) {
self.underlyingImage = nil;
MWLog(@"Photo from asset library error: %@",error);
[self performSelectorOnMainThread:@selector(imageLoadingComplete) withObject:nil waitUntilDone:NO];
}];
这里的AssetsLibrary是一个有点跟不上 iOS 应用发展步伐以及代码设计原则但确实强大的框架,在 iOS 8 出现之后,苹果提供了PhotoKit框架。
PHImageManager *imageManager = [PHImageManager defaultManager];
PHImageRequestOptions *options = [PHImageRequestOptions new];
options.networkAccessAllowed = YES;
options.resizeMode = PHImageRequestOptionsResizeModeFast;
options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
options.synchronous = false;
options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithDouble: progress], @"progress",
self, @"photo", nil];
_assetRequestID = [imageManager requestImageForAsset:asset targetSize:targetSize contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage *result, NSDictionary *info) {
dispatch_async(dispatch_get_main_queue(), ^{
self.underlyingImage = result;
[self imageLoadingComplete];
});
}];
1.2 图片的描述部分(MWCaptionView.h)
描述部分比较简单就是一个view上面放了一个label,作者做了对nil的处理。显现与隐藏没有在这里面定义。
本人能力有限,有不足或者错误之处欢迎读者朋友讨论指正,谢谢~
未完待续。