添加文件

This commit is contained in:
wu736139669
2015-06-29 11:47:53 +08:00
parent b3531f3da8
commit 2f091961ce
2 changed files with 366 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
//
// UIImageViewReloading.h
// XiaoYu
// 可以显示进度,还可以失败重新下载
// Created by xmfish on 14-8-21.
// Copyright (c) 2014年 Benson. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "UIImageView+WebCache.h"
typedef NS_ENUM(NSInteger, LKImageViewStatus){
LKImageViewStatusNone = 0,
LKImageViewStatusLoaded = 1,
LKImageViewStatusLoading = 2,
LKImageViewStatusFail = 3
};
@interface UIImageView(Reloading)
//加载的图片 url地址 可以是 NSString 或 NSURL
@property(copy, nonatomic) id imageURL;
//这个不会设置 image 只会保存ImageURL
- (void)setImageURLFromCache:(id)imageURL;
//当前状态
@property LKImageViewStatus status;
//图片点击事件 不用再手动添加UITapGestureRecognizer
@property(copy, nonatomic) void(^onTouchTapBlock)(UIImageView *imageView);
//重新加载图片
- (void)reloadImageURL;
@end
+334
View File
@@ -0,0 +1,334 @@
//
// UIImageViewReloading.m
// XiaoYu
//
// Created by xmfish on 14-8-21.
// Copyright (c) 2014年 Benson. All rights reserved.
//
#import "UIImageView+Reloading.h"
#import <execinfo.h>
#import <objc/runtime.h>
#import <objc/message.h>
@implementation NSObject (Swizzle)
+ (BOOL)jr_swizzleMethod:(SEL)origSel_ withMethod:(SEL)altSel_ error:(NSError**)error_ {
Method origMethod = class_getInstanceMethod(self, origSel_);
if (!origMethod) {
return NO;
}
Method altMethod = class_getInstanceMethod(self, altSel_);
if (!altMethod) {
return NO;
}
class_addMethod(self,
origSel_,
class_getMethodImplementation(self, origSel_),
method_getTypeEncoding(origMethod));
class_addMethod(self,
altSel_,
class_getMethodImplementation(self, altSel_),
method_getTypeEncoding(altMethod));
method_exchangeImplementations(class_getInstanceMethod(self, origSel_), class_getInstanceMethod(self, altSel_));
return YES;
}
+ (BOOL)jr_swizzleClassMethod:(SEL)origSel_ withClassMethod:(SEL)altSel_ error:(NSError**)error_ {
return [object_getClass((id)self) jr_swizzleMethod:origSel_ withMethod:altSel_ error:error_];
}
@end
static char imageURLKey;
static char imageStatusKey;
static char imageTapEventKey;
static char imageOriginalModelKey;
@implementation UIImageView (SY)
+ (void)load
{
[UIImageView jr_swizzleMethod:@selector(cancelCurrentImageLoad) withMethod:@selector(sy_cancelCurrentImageLoad) error:nil];
}
- (UIButton *)sy_progressView:(BOOL)isCreate
{
static char imageProgressKey;
UIButton *progressView = objc_getAssociatedObject(self, &imageProgressKey);
if (isCreate)
{
if (progressView == nil)
{
progressView = [UIButton buttonWithType:UIButtonTypeCustom];
progressView.frame = self.bounds;
progressView.hidden = YES;
progressView.backgroundColor = [UIColor clearColor];
[progressView setTitle:@"点击加载图片" forState:UIControlStateNormal];
[progressView setTitle:@"图片加载中" forState:UIControlStateDisabled];
progressView.titleLabel.shadowColor = [UIColor whiteColor];
progressView.titleLabel.shadowOffset = CGSizeMake(1, 1);
[progressView setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal];
[progressView setTitleColor:[UIColor lightGrayColor] forState:UIControlStateDisabled];
progressView.titleLabel.adjustsFontSizeToFitWidth = YES;
CGSize size = CGSizeMake(progressView.frame.size.width,2000);
CGSize labelsize = [progressView.titleLabel.text sizeWithFont:progressView.titleLabel.font constrainedToSize:size lineBreakMode:NSLineBreakByCharWrapping];
progressView.frame = CGRectMake(0.0, 0.0, labelsize.width, labelsize.height);
progressView.center = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2);
[progressView addTarget:self action:@selector(reloadImageURL) forControlEvents:UIControlEventTouchUpInside];
progressView.enabled = NO;
objc_setAssociatedObject(self, &imageProgressKey, progressView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
__weak UIImageView* wself = self;
dispatch_async(dispatch_get_main_queue(), ^{
[wself addSubview:progressView];
});
}
return progressView;
}
- (UIViewContentMode)originalViewContentMode
{
NSNumber *value = objc_getAssociatedObject(self, &imageOriginalModelKey);
int mode = -1;
if (value)
{
mode = [value intValue];
}
if (mode < 0 || mode > UIViewContentModeBottomRight)
{
return -1;
}
else
{
return mode;
}
}
- (void)setOriginalViewContentMode:(UIViewContentMode)originalViewContentMode
{
NSNumber *value = [[NSNumber alloc] initWithInt:originalViewContentMode];
objc_setAssociatedObject(self, &imageOriginalModelKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (LKImageViewStatus)status
{
NSNumber *value = objc_getAssociatedObject(self, &imageStatusKey);
if (value)
{
return [value intValue];
}
return LKImageViewStatusNone;
}
- (void)setStatus:(LKImageViewStatus)status
{
objc_setAssociatedObject(self, &imageStatusKey, @(status), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)setImageURLFromCache:(id)imageURL
{
[self sy_loadTapEvent];
self.status = LKImageViewStatusLoaded;
objc_setAssociatedObject(self, &imageURLKey, imageURL, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (void)setImageURL:(id)imageURL
{
[self sy_loadTapEvent];
objc_setAssociatedObject(self, &imageURLKey, imageURL, OBJC_ASSOCIATION_COPY_NONATOMIC);
if (imageURL)
{
[self reloadImageURL];
}
else
{
[self sy_cancelCurrentImageLoad];
self.image = nil;
self.backgroundColor = [UIColor colorWithRed:233/255.0 green:228/255.0 blue:223/255.0 alpha:1];
self.status = LKImageViewStatusNone;
UIButton *pv = [self sy_progressView:NO];
[pv removeFromSuperview];
}
}
- (void)sy_loadTapEvent
{
static char tapEventLoadedKey;
id loaded = objc_getAssociatedObject(self, &tapEventLoadedKey);
if (loaded == nil)
{
self.userInteractionEnabled = YES;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(sy_handleTapEvent:)];
[self addGestureRecognizer:tap];
objc_setAssociatedObject(self, &tapEventLoadedKey, @(YES), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
}
- (id)imageURL
{
return objc_getAssociatedObject(self, &imageURLKey);
}
- (void)sy_cancelCurrentImageLoad
{
if (self.imageURL)
{
void *callstack[2];
int frames = backtrace(callstack, 2);
char **strs = backtrace_symbols(callstack, 2);
NSString *func_name = nil;
if (frames > 1 && strs && strs[1])
{
func_name = [NSString stringWithUTF8String:strs[1]];
}
free(strs);
//如果从外部调用 cancelImageLoad 才进行扫尾工作
if ([func_name rangeOfString:@"UIImageView(WebCache)"].length == 0)
{
UIButton *pv = [self sy_progressView:NO];
// pv.hidden = YES;
[pv removeFromSuperview];
self.status = LKImageViewStatusNone;
}
}
[self sy_cancelCurrentImageLoad];
}
- (void)reloadImageURL
{
id imageURL = self.imageURL;
if ([imageURL isKindOfClass:[NSString class]])
{
if ([imageURL isEqualToString:@""] == NO)
{
imageURL = [NSURL URLWithString:imageURL];
}
}
if ([imageURL isKindOfClass:[NSURL class]] == NO)
{
return;
}
[self sy_cancelCurrentImageLoad];
self.image = nil;
self.backgroundColor = [UIColor colorWithRed:233/255.0 green:228/255.0 blue:223/255.0 alpha:1];
__weak UIImageView *wself = self;
if([self originalViewContentMode] < 0){
[self setOriginalViewContentMode:self.contentMode];
}
self.contentMode = UIViewContentModeScaleAspectFill;
self.status = LKImageViewStatusLoading;
__weak __block UIButton *pv = [self sy_progressView:YES];
dispatch_async(dispatch_get_main_queue(), ^{
pv.hidden = NO;
pv.enabled = NO;
});
[self sd_setImageWithURL:imageURL placeholderImage:self.image options:SDWebImageRetryFailed progress:^(NSInteger receivedSize, NSInteger expectedSize) {
float pvalue = MAX(0, MIN(1, receivedSize / (float) expectedSize));
dispatch_async(dispatch_get_main_queue(), ^{
// [pv.titleLabel setText:[NSString stringWithFormat:@"图片加载中%.1f %%",pvalue*100]];
[pv setTitle:[NSString stringWithFormat:@"图片加载中%.1f %%",pvalue*100] forState:UIControlStateDisabled];
pv.hidden = NO;
});
} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if(!pv){
pv = [wself sy_progressView:NO];
}
if (image)
{
pv.hidden = YES;
dispatch_async(dispatch_get_main_queue(), ^{
[pv removeFromSuperview];
});
if([wself originalViewContentMode]>=0){
if(wself.contentMode != [wself originalViewContentMode]){
wself.contentMode = [wself originalViewContentMode];
[wself setNeedsDisplay];
}
}
else if (wself.contentMode != UIViewContentModeScaleAspectFill)
{
wself.contentMode = UIViewContentModeScaleAspectFill;
[wself setNeedsDisplay];
}
wself.status = LKImageViewStatusLoaded;
wself.backgroundColor = [UIColor clearColor];
[wself setOriginalViewContentMode:-1];
}
else
{
if (error)
{
wself.status = LKImageViewStatusFail;
[wself setOriginalViewContentMode:-1];
dispatch_async(dispatch_get_main_queue(), ^{
pv.enabled = YES;
});
}
}
}];
}
- (void)setOnTouchTapBlock:(void (^)(UIImageView *))onTouchTapBlock
{
[self sy_loadTapEvent];
objc_setAssociatedObject(self, &imageTapEventKey, onTouchTapBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (void (^)(UIImageView *))onTouchTapBlock
{
return objc_getAssociatedObject(self, &imageTapEventKey);
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
if (self.imageURL && self.status != LKImageViewStatusFail && self.onTouchTapBlock == nil)
{
return NO;
}
if (self.status == LKImageViewStatusLoading || self.status == LKImageViewStatusFail) {
UIButton* pv = [self sy_progressView:NO];
if (self.status == LKImageViewStatusFail && [pv pointInside:[self convertPoint:point toView:pv] withEvent:event]) {
return YES;
}
return NO;
}
return [super pointInside:point withEvent:event];
}
- (void)sy_handleTapEvent:(UITapGestureRecognizer *)sender
{
switch (self.status)
{
case LKImageViewStatusFail:
[self reloadImageURL];
break;
default:
if (self.onTouchTapBlock)
{
self.onTouchTapBlock(self);
}
break;
}
}
@end