Commit a0c1ef468ed3f27ed7cb3b33a0b86802650ce821
1 parent
e5408852
0.1.3 YBImageBrowser 通过pod 形式集成
Showing
55 changed files
with
4 additions
and
4779 deletions
Too many changes to show.
To preserve performance only 55 of 69 files are displayed.
CNLiveOrganizationValidationModule.podspec
| @@ -8,7 +8,7 @@ | @@ -8,7 +8,7 @@ | ||
| 8 | 8 | ||
| 9 | Pod::Spec.new do |s| | 9 | Pod::Spec.new do |s| |
| 10 | s.name = 'CNLiveOrganizationValidationModule' | 10 | s.name = 'CNLiveOrganizationValidationModule' |
| 11 | - s.version = '0.1.2' | 11 | + s.version = '0.1.3' |
| 12 | s.summary = '机构认证模块' | 12 | s.summary = '机构认证模块' |
| 13 | 13 | ||
| 14 | # This description is used to generate tags and improve search results. | 14 | # This description is used to generate tags and improve search results. |
| @@ -78,7 +78,7 @@ Pod::Spec.new do |s| | @@ -78,7 +78,7 @@ Pod::Spec.new do |s| | ||
| 78 | ######################################## | 78 | ######################################## |
| 79 | s.dependency 'CNLiveNewTripartiteManagement/RSKImageCropper' | 79 | s.dependency 'CNLiveNewTripartiteManagement/RSKImageCropper' |
| 80 | # #相册展示 | 80 | # #相册展示 |
| 81 | -# s.dependency 'YBImageBrowser' | 81 | + s.dependency 'YBImageBrowser' |
| 82 | 82 | ||
| 83 | 83 | ||
| 84 | 84 |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/Controller/CNLiveBOraganizationDetailController.m
| @@ -20,8 +20,8 @@ | @@ -20,8 +20,8 @@ | ||
| 20 | #import <QMUIKit/QMUIKit.h> | 20 | #import <QMUIKit/QMUIKit.h> |
| 21 | //#import <YYKit/YYKit.h> | 21 | //#import <YYKit/YYKit.h> |
| 22 | #import <objc/runtime.h> | 22 | #import <objc/runtime.h> |
| 23 | -#import "YBImageBrowser.h" | ||
| 24 | -#import "YBIBImageData.h" | 23 | +#import <YBImageBrowser/YBImageBrowser.h> |
| 24 | +//#import "YBIBImageData.h" | ||
| 25 | #import "UIImage+OrganizationValidation.h" | 25 | #import "UIImage+OrganizationValidation.h" |
| 26 | 26 | ||
| 27 | 27 |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/AuxiliaryView/YBIBAuxiliaryViewHandler.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBAuxiliaryViewHandler.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/27. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import <UIKit/UIKit.h> | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | -@protocol YBIBAuxiliaryViewHandler <NSObject> | ||
| 14 | - | ||
| 15 | -@required | ||
| 16 | - | ||
| 17 | -/// 展示正确情况的提示 | ||
| 18 | -- (void)yb_showCorrectToastWithContainer:(UIView *)container text:(NSString *)text; | ||
| 19 | -/// 展示错误情况的提示 | ||
| 20 | -- (void)yb_showIncorrectToastWithContainer:(UIView *)container text:(NSString *)text; | ||
| 21 | -/// 隐藏所有提示 | ||
| 22 | -- (void)yb_hideToastWithContainer:(UIView *)container; | ||
| 23 | - | ||
| 24 | -/// 展示加载视图 | ||
| 25 | -- (void)yb_showLoadingWithContainer:(UIView *)container; | ||
| 26 | -/// 展示带进度的加载视图 | ||
| 27 | -- (void)yb_showLoadingWithContainer:(UIView *)container progress:(CGFloat)progress; | ||
| 28 | -/// 展示带文字的视图 | ||
| 29 | -- (void)yb_showLoadingWithContainer:(UIView *)container text:(NSString *)text; | ||
| 30 | -/// 隐藏所有视图 | ||
| 31 | -- (void)yb_hideLoadingWithContainer:(UIView *)container; | ||
| 32 | - | ||
| 33 | -@end | ||
| 34 | - | ||
| 35 | -@interface YBIBAuxiliaryViewHandler : NSObject <YBIBAuxiliaryViewHandler> | ||
| 36 | - | ||
| 37 | -@end | ||
| 38 | - | ||
| 39 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/AuxiliaryView/YBIBAuxiliaryViewHandler.m deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBAuxiliaryViewHandler.m | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/27. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBAuxiliaryViewHandler.h" | ||
| 10 | -#import "YBIBToastView.h" | ||
| 11 | -#import "YBIBLoadingView.h" | ||
| 12 | - | ||
| 13 | -@implementation YBIBAuxiliaryViewHandler | ||
| 14 | - | ||
| 15 | -#pragma mark - <YBIBAuxiliaryViewHandler> | ||
| 16 | - | ||
| 17 | -- (void)yb_showCorrectToastWithContainer:(UIView *)container text:(NSString *)text { | ||
| 18 | - [container ybib_showHookToast:text]; | ||
| 19 | -} | ||
| 20 | - | ||
| 21 | -- (void)yb_showIncorrectToastWithContainer:(UIView *)container text:(NSString *)text { | ||
| 22 | - [container ybib_showForkToast:text]; | ||
| 23 | -} | ||
| 24 | - | ||
| 25 | -- (void)yb_hideToastWithContainer:(UIView *)container { | ||
| 26 | - [container ybib_hideToast]; | ||
| 27 | -} | ||
| 28 | - | ||
| 29 | -- (void)yb_showLoadingWithContainer:(UIView *)container { | ||
| 30 | - [container ybib_showLoading]; | ||
| 31 | -} | ||
| 32 | - | ||
| 33 | -- (void)yb_showLoadingWithContainer:(UIView *)container progress:(CGFloat)progress { | ||
| 34 | - [container ybib_showLoadingWithProgress:progress]; | ||
| 35 | -} | ||
| 36 | - | ||
| 37 | -- (void)yb_showLoadingWithContainer:(UIView *)container text:(NSString *)text { | ||
| 38 | - [container ybib_showLoadingWithText:text click:nil]; | ||
| 39 | -} | ||
| 40 | - | ||
| 41 | -- (void)yb_hideLoadingWithContainer:(UIView *)container { | ||
| 42 | - [container ybib_hideLoading]; | ||
| 43 | -} | ||
| 44 | - | ||
| 45 | -@end |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/AuxiliaryView/YBIBLoadingView.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBLoadingView.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2018/9/1. | ||
| 6 | -// Copyright © 2018年 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import <UIKit/UIKit.h> | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | -@interface UIView (YBIBLoading) | ||
| 14 | - | ||
| 15 | -- (void)ybib_showLoading; | ||
| 16 | - | ||
| 17 | -- (void)ybib_showLoadingWithProgress:(CGFloat)progress; | ||
| 18 | - | ||
| 19 | -- (void)ybib_showLoadingWithText:(NSString *)text click:(nullable void(^)(void))click; | ||
| 20 | - | ||
| 21 | -- (void)ybib_hideLoading; | ||
| 22 | - | ||
| 23 | -@end | ||
| 24 | - | ||
| 25 | - | ||
| 26 | -@interface YBIBLoadingView : UIView | ||
| 27 | - | ||
| 28 | -- (void)show; | ||
| 29 | - | ||
| 30 | -- (void)showProgress:(CGFloat)progress; | ||
| 31 | - | ||
| 32 | -- (void)showText:(NSString *)text click:(void(^)(void))click; | ||
| 33 | - | ||
| 34 | -@end | ||
| 35 | - | ||
| 36 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/AuxiliaryView/YBIBLoadingView.m deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBLoadingView.m | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2018/9/1. | ||
| 6 | -// Copyright © 2018年 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBLoadingView.h" | ||
| 10 | -#import "YBIBIconManager.h" | ||
| 11 | -#import <objc/runtime.h> | ||
| 12 | - | ||
| 13 | -@interface UIView () | ||
| 14 | -@property (nonatomic, strong, readonly) YBIBLoadingView *ybib_loading; | ||
| 15 | -@end | ||
| 16 | - | ||
| 17 | -@implementation UIView (YBIBLoading) | ||
| 18 | - | ||
| 19 | -- (void)ybib_showLoadingWithProgress:(CGFloat)progress { | ||
| 20 | - [self ybib_addLoadingView]; | ||
| 21 | - [self.ybib_loading showProgress:progress]; | ||
| 22 | -} | ||
| 23 | - | ||
| 24 | -- (void)ybib_showLoading { | ||
| 25 | - [self ybib_addLoadingView]; | ||
| 26 | - [self.ybib_loading show]; | ||
| 27 | -} | ||
| 28 | - | ||
| 29 | -- (void)ybib_showLoadingWithText:(NSString *)text click:(void (^)(void))click { | ||
| 30 | - [self ybib_addLoadingView]; | ||
| 31 | - [self.ybib_loading showText:text click:click]; | ||
| 32 | -} | ||
| 33 | - | ||
| 34 | -- (void)ybib_addLoadingView { | ||
| 35 | - YBIBLoadingView *loading = self.ybib_loading; | ||
| 36 | - if (!loading.superview) { | ||
| 37 | - [self addSubview:loading]; | ||
| 38 | - loading.translatesAutoresizingMaskIntoConstraints = NO; | ||
| 39 | - NSLayoutConstraint *layA = [NSLayoutConstraint constraintWithItem:loading attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1 constant:0]; | ||
| 40 | - NSLayoutConstraint *layB = [NSLayoutConstraint constraintWithItem:loading attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1 constant:0]; | ||
| 41 | - NSLayoutConstraint *layC = [NSLayoutConstraint constraintWithItem:loading attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1 constant:0]; | ||
| 42 | - NSLayoutConstraint *layD = [NSLayoutConstraint constraintWithItem:loading attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1 constant:0]; | ||
| 43 | - [self addConstraints:@[layA, layB, layC, layD]]; | ||
| 44 | - } | ||
| 45 | -} | ||
| 46 | - | ||
| 47 | -- (void)ybib_hideLoading { | ||
| 48 | - YBIBLoadingView *loading = self.ybib_loading; | ||
| 49 | - if (loading && loading.superview) { | ||
| 50 | - [loading removeFromSuperview]; | ||
| 51 | - } | ||
| 52 | -} | ||
| 53 | - | ||
| 54 | -static void *YBIBLoadingKey = &YBIBLoadingKey; | ||
| 55 | -- (void)setYbib_loading:(YBIBLoadingView *)ybib_loading { | ||
| 56 | - objc_setAssociatedObject(self, YBIBLoadingKey, ybib_loading, OBJC_ASSOCIATION_RETAIN_NONATOMIC); | ||
| 57 | -} | ||
| 58 | -- (YBIBLoadingView *)ybib_loading { | ||
| 59 | - YBIBLoadingView *loading = objc_getAssociatedObject(self, YBIBLoadingKey); | ||
| 60 | - if (!loading) { | ||
| 61 | - loading = [YBIBLoadingView new]; | ||
| 62 | - self.ybib_loading = loading; | ||
| 63 | - } | ||
| 64 | - return loading; | ||
| 65 | -} | ||
| 66 | - | ||
| 67 | -@end | ||
| 68 | - | ||
| 69 | - | ||
| 70 | -@interface YBIBProgressDrawView : UIView | ||
| 71 | -@property (nonatomic, assign) CGFloat progress; | ||
| 72 | -@end | ||
| 73 | -@implementation YBIBProgressDrawView | ||
| 74 | -- (void)drawRect:(CGRect)rect { | ||
| 75 | - if (self.isHidden) return; | ||
| 76 | - | ||
| 77 | - CGFloat progress = (isnan(_progress) || isinf(_progress) || _progress < 0) ? 0 : _progress; | ||
| 78 | - | ||
| 79 | - CGFloat radius = 17; | ||
| 80 | - CGFloat strokeWidth = 3; | ||
| 81 | - CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); | ||
| 82 | - | ||
| 83 | - [[UIColor lightGrayColor] setStroke]; | ||
| 84 | - UIBezierPath *bottomPath = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:0 endAngle:M_PI * 2 clockwise:YES]; | ||
| 85 | - bottomPath.lineWidth = 4.0; | ||
| 86 | - bottomPath.lineCapStyle = kCGLineCapRound; | ||
| 87 | - bottomPath.lineJoinStyle = kCGLineCapRound; | ||
| 88 | - [bottomPath stroke]; | ||
| 89 | - | ||
| 90 | - [[UIColor whiteColor] setStroke]; | ||
| 91 | - UIBezierPath *activePath = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:-M_PI / 2.0 endAngle:M_PI * 2 * progress - M_PI / 2.0 clockwise:true]; | ||
| 92 | - activePath.lineWidth = strokeWidth; | ||
| 93 | - activePath.lineCapStyle = kCGLineCapRound; | ||
| 94 | - activePath.lineJoinStyle = kCGLineCapRound; | ||
| 95 | - [activePath stroke]; | ||
| 96 | - | ||
| 97 | - NSShadow *shadow = [NSShadow new]; | ||
| 98 | - shadow.shadowBlurRadius = 4; | ||
| 99 | - shadow.shadowOffset = CGSizeMake(0, 1); | ||
| 100 | - shadow.shadowColor = UIColor.darkGrayColor; | ||
| 101 | - NSString *string = [NSString stringWithFormat:@"%.0lf%@", progress * 100, @"%"]; | ||
| 102 | - NSMutableAttributedString *atts = [[NSMutableAttributedString alloc] initWithString:string attributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:10], NSForegroundColorAttributeName:[UIColor whiteColor], NSShadowAttributeName:shadow}]; | ||
| 103 | - CGSize size = atts.size; | ||
| 104 | - [atts drawAtPoint:CGPointMake(center.x - size.width / 2.0, center.y - size.height / 2.0)]; | ||
| 105 | -} | ||
| 106 | -@end | ||
| 107 | - | ||
| 108 | - | ||
| 109 | -typedef NS_ENUM(NSUInteger, YBImageBrowserProgressType) { | ||
| 110 | - YBImageBrowserProgressTypeProgress, | ||
| 111 | - YBImageBrowserProgressTypeLoad, | ||
| 112 | - YBImageBrowserProgressTypeText | ||
| 113 | -}; | ||
| 114 | - | ||
| 115 | -@interface YBIBLoadingView () { | ||
| 116 | - YBImageBrowserProgressType _type; | ||
| 117 | -} | ||
| 118 | -@property (nonatomic, strong) UILabel *textLabel; | ||
| 119 | -@property (nonatomic, strong) UIImageView *imageView; | ||
| 120 | -@property (nonatomic, strong) YBIBProgressDrawView *drawView; | ||
| 121 | -@property (nonatomic, copy) void(^clickTextLabelBlock)(void); | ||
| 122 | -@end | ||
| 123 | - | ||
| 124 | -@implementation YBIBLoadingView | ||
| 125 | - | ||
| 126 | -#pragma mark life cycle | ||
| 127 | - | ||
| 128 | -- (instancetype)initWithFrame:(CGRect)frame { | ||
| 129 | - self = [super initWithFrame:frame]; | ||
| 130 | - if (self) { | ||
| 131 | - self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0]; | ||
| 132 | - self.userInteractionEnabled = NO; | ||
| 133 | - | ||
| 134 | - [self addSubview:self.drawView]; | ||
| 135 | - [self addSubview:self.textLabel]; | ||
| 136 | - [self addSubview:self.imageView]; | ||
| 137 | - } | ||
| 138 | - return self; | ||
| 139 | -} | ||
| 140 | - | ||
| 141 | -- (void)updateConstraints { | ||
| 142 | - self.textLabel.translatesAutoresizingMaskIntoConstraints = NO; | ||
| 143 | - NSLayoutConstraint *layA = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1 constant:20]; | ||
| 144 | - NSLayoutConstraint *layB = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1 constant:-20]; | ||
| 145 | - NSLayoutConstraint *layC = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]; | ||
| 146 | - | ||
| 147 | - self.imageView.translatesAutoresizingMaskIntoConstraints = NO; | ||
| 148 | - NSLayoutConstraint *layE = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]; | ||
| 149 | - NSLayoutConstraint *layF = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]; | ||
| 150 | - | ||
| 151 | - self.drawView.translatesAutoresizingMaskIntoConstraints = NO; | ||
| 152 | - NSLayoutConstraint *layG = [NSLayoutConstraint constraintWithItem:self.drawView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]; | ||
| 153 | - NSLayoutConstraint *layH = [NSLayoutConstraint constraintWithItem:self.drawView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]; | ||
| 154 | - NSLayoutConstraint *layI = [NSLayoutConstraint constraintWithItem:self.drawView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:50]; | ||
| 155 | - NSLayoutConstraint *layJ = [NSLayoutConstraint constraintWithItem:self.drawView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:50]; | ||
| 156 | - | ||
| 157 | - [self addConstraints:@[layA, layB, layC, layE, layF, layG, layH, layI, layJ]]; | ||
| 158 | - [super updateConstraints]; | ||
| 159 | -} | ||
| 160 | - | ||
| 161 | -#pragma mark public | ||
| 162 | - | ||
| 163 | -- (void)showProgress:(CGFloat)progress { | ||
| 164 | - self.userInteractionEnabled = NO; | ||
| 165 | - _type = YBImageBrowserProgressTypeProgress; | ||
| 166 | - self.drawView.hidden = NO; | ||
| 167 | - self.textLabel.hidden = YES; | ||
| 168 | - self.imageView.hidden = YES; | ||
| 169 | - [self stopImageViewAnimation]; | ||
| 170 | - | ||
| 171 | - self.drawView.progress = progress; | ||
| 172 | - [self.drawView setNeedsDisplay]; | ||
| 173 | -} | ||
| 174 | - | ||
| 175 | -- (void)show { | ||
| 176 | - self.userInteractionEnabled = NO; | ||
| 177 | - _type = YBImageBrowserProgressTypeLoad; | ||
| 178 | - self.drawView.hidden = YES; | ||
| 179 | - self.textLabel.hidden = YES; | ||
| 180 | - self.imageView.hidden = NO; | ||
| 181 | - | ||
| 182 | - [self startImageViewAnimation]; | ||
| 183 | - [self.drawView setNeedsDisplay]; | ||
| 184 | -} | ||
| 185 | - | ||
| 186 | -- (void)startImageViewAnimation { | ||
| 187 | - CABasicAnimation *ra = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; | ||
| 188 | - ra.toValue = [NSNumber numberWithFloat:M_PI * 2]; | ||
| 189 | - ra.duration = 1; | ||
| 190 | - ra.cumulative = YES; | ||
| 191 | - ra.repeatCount = HUGE_VALF; | ||
| 192 | - ra.removedOnCompletion = NO; | ||
| 193 | - ra.fillMode = kCAFillModeForwards; | ||
| 194 | - [self.imageView.layer addAnimation:ra forKey:@"ra"]; | ||
| 195 | -} | ||
| 196 | - | ||
| 197 | -- (void)stopImageViewAnimation { | ||
| 198 | - [self.imageView.layer removeAllAnimations]; | ||
| 199 | -} | ||
| 200 | - | ||
| 201 | -- (void)showText:(NSString *)text click:(void (^)(void))click { | ||
| 202 | - self.userInteractionEnabled = click ? YES : NO; | ||
| 203 | - _type = YBImageBrowserProgressTypeText; | ||
| 204 | - self.drawView.hidden = YES; | ||
| 205 | - self.textLabel.hidden = NO; | ||
| 206 | - self.imageView.hidden = YES; | ||
| 207 | - [self stopImageViewAnimation]; | ||
| 208 | - | ||
| 209 | - self.textLabel.text = text; | ||
| 210 | - self.clickTextLabelBlock = click; | ||
| 211 | - [self.drawView setNeedsDisplay]; | ||
| 212 | -} | ||
| 213 | - | ||
| 214 | -#pragma mark - touch event | ||
| 215 | - | ||
| 216 | -- (void)respondsToTapTextlabel { | ||
| 217 | - if (self.clickTextLabelBlock) { | ||
| 218 | - self.clickTextLabelBlock(); | ||
| 219 | - } | ||
| 220 | -} | ||
| 221 | - | ||
| 222 | -#pragma mark - getter | ||
| 223 | - | ||
| 224 | -- (YBIBProgressDrawView *)drawView { | ||
| 225 | - if (!_drawView) { | ||
| 226 | - _drawView = [YBIBProgressDrawView new]; | ||
| 227 | - _drawView.backgroundColor = [UIColor clearColor]; | ||
| 228 | - } | ||
| 229 | - return _drawView; | ||
| 230 | -} | ||
| 231 | - | ||
| 232 | -- (UILabel *)textLabel { | ||
| 233 | - if (!_textLabel) { | ||
| 234 | - _textLabel = [UILabel new]; | ||
| 235 | - _textLabel.textColor = [UIColor whiteColor]; | ||
| 236 | - _textLabel.numberOfLines = 0; | ||
| 237 | - _textLabel.font = [UIFont systemFontOfSize:14]; | ||
| 238 | - _textLabel.textAlignment = NSTextAlignmentCenter; | ||
| 239 | - UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(respondsToTapTextlabel)]; | ||
| 240 | - [_textLabel addGestureRecognizer:tapGesture]; | ||
| 241 | - _textLabel.userInteractionEnabled = YES; | ||
| 242 | - } | ||
| 243 | - return _textLabel; | ||
| 244 | -} | ||
| 245 | - | ||
| 246 | -- (UIImageView *)imageView { | ||
| 247 | - if (!_imageView) { | ||
| 248 | - _imageView = [UIImageView new]; | ||
| 249 | - _imageView.image = [YBIBIconManager sharedManager].loadingImage(); | ||
| 250 | - _imageView.layer.shadowColor = UIColor.darkGrayColor.CGColor; | ||
| 251 | - _imageView.layer.shadowOffset = CGSizeMake(0, 1); | ||
| 252 | - _imageView.layer.shadowOpacity = 1; | ||
| 253 | - _imageView.layer.shadowRadius = 4; | ||
| 254 | - } | ||
| 255 | - return _imageView; | ||
| 256 | -} | ||
| 257 | - | ||
| 258 | -@end |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/AuxiliaryView/YBIBToastView.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBToastView.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/20. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import <UIKit/UIKit.h> | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | -@interface UIView (YBIBToast) | ||
| 14 | - | ||
| 15 | -- (void)ybib_showHookToast:(NSString *)text; | ||
| 16 | - | ||
| 17 | -- (void)ybib_showForkToast:(NSString *)text; | ||
| 18 | - | ||
| 19 | -- (void)ybib_hideToast; | ||
| 20 | - | ||
| 21 | -@end | ||
| 22 | - | ||
| 23 | - | ||
| 24 | -typedef NS_ENUM(NSInteger, YBIBToastType) { | ||
| 25 | - YBIBToastTypeNone, | ||
| 26 | - YBIBToastTypeHook, | ||
| 27 | - YBIBToastTypeFork | ||
| 28 | -}; | ||
| 29 | - | ||
| 30 | -@interface YBIBToastView : UIView | ||
| 31 | - | ||
| 32 | -- (void)showWithText:(NSString *)text type:(YBIBToastType)type; | ||
| 33 | - | ||
| 34 | -@end | ||
| 35 | - | ||
| 36 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/AuxiliaryView/YBIBToastView.m deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBToastView.m | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/20. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBToastView.h" | ||
| 10 | -#import <objc/runtime.h> | ||
| 11 | - | ||
| 12 | -@interface UIView () | ||
| 13 | -@property (nonatomic, strong, readonly) YBIBToastView *ybib_toast; | ||
| 14 | -@end | ||
| 15 | - | ||
| 16 | -@implementation UIView (YBIBToast) | ||
| 17 | - | ||
| 18 | -- (void)ybib_showHookToast:(NSString *)text { | ||
| 19 | - [self ybib_showToastWithText:text type:YBIBToastTypeHook hideAfterDelay:1.7]; | ||
| 20 | -} | ||
| 21 | - | ||
| 22 | -- (void)ybib_showForkToast:(NSString *)text { | ||
| 23 | - [self ybib_showToastWithText:text type:YBIBToastTypeFork hideAfterDelay:1.7]; | ||
| 24 | -} | ||
| 25 | - | ||
| 26 | -- (void)ybib_showToastWithText:(NSString *)text type:(YBIBToastType)type hideAfterDelay:(NSTimeInterval)delay { | ||
| 27 | - [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(ybib_hideToast) object:nil]; | ||
| 28 | - | ||
| 29 | - YBIBToastView *toast = self.ybib_toast; | ||
| 30 | - if (!toast.superview) { | ||
| 31 | - [self addSubview:toast]; | ||
| 32 | - toast.translatesAutoresizingMaskIntoConstraints = NO; | ||
| 33 | - NSLayoutConstraint *layA = [NSLayoutConstraint constraintWithItem:toast attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]; | ||
| 34 | - NSLayoutConstraint *layB = [NSLayoutConstraint constraintWithItem:toast attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]; | ||
| 35 | - NSLayoutConstraint *layC = [NSLayoutConstraint constraintWithItem:toast attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1 constant:40]; | ||
| 36 | - NSLayoutConstraint *layD = [NSLayoutConstraint constraintWithItem:toast attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationLessThanOrEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1 constant:-40]; | ||
| 37 | - [self addConstraints:@[layA, layB, layC, layD]]; | ||
| 38 | - } | ||
| 39 | - | ||
| 40 | - [toast showWithText:text type:type]; | ||
| 41 | - [self performSelector:@selector(ybib_hideToast) withObject:nil afterDelay:delay]; | ||
| 42 | -} | ||
| 43 | - | ||
| 44 | -- (void)ybib_hideToast { | ||
| 45 | - YBIBToastView *toast = self.ybib_toast; | ||
| 46 | - if (toast && toast.superview) { | ||
| 47 | - [UIView animateWithDuration:0.25 animations:^{ | ||
| 48 | - toast.alpha = 0; | ||
| 49 | - } completion:^(BOOL finished) { | ||
| 50 | - [toast removeFromSuperview]; | ||
| 51 | - toast.alpha = 1; | ||
| 52 | - }]; | ||
| 53 | - } | ||
| 54 | -} | ||
| 55 | - | ||
| 56 | -static void *YBIBToastKey = &YBIBToastKey; | ||
| 57 | -- (void)setYbib_toast:(YBIBToastView *)ybib_toast { | ||
| 58 | - objc_setAssociatedObject(self, YBIBToastKey, ybib_toast, OBJC_ASSOCIATION_RETAIN_NONATOMIC); | ||
| 59 | -} | ||
| 60 | -- (YBIBToastView *)ybib_toast { | ||
| 61 | - YBIBToastView *toast = objc_getAssociatedObject(self, YBIBToastKey); | ||
| 62 | - if (!toast) { | ||
| 63 | - toast = [YBIBToastView new]; | ||
| 64 | - self.ybib_toast = toast; | ||
| 65 | - } | ||
| 66 | - return toast; | ||
| 67 | -} | ||
| 68 | - | ||
| 69 | -@end | ||
| 70 | - | ||
| 71 | - | ||
| 72 | -@interface YBIBToastView () { | ||
| 73 | - YBIBToastType _type; | ||
| 74 | - CAShapeLayer *_shapeLayer; | ||
| 75 | -} | ||
| 76 | -@property (nonatomic, strong) UILabel *textLabel; | ||
| 77 | -@end | ||
| 78 | - | ||
| 79 | -@implementation YBIBToastView | ||
| 80 | - | ||
| 81 | -#pragma mark - life cycle | ||
| 82 | - | ||
| 83 | -- (instancetype)initWithFrame:(CGRect)frame { | ||
| 84 | - self = [super initWithFrame:frame]; | ||
| 85 | - if (self) { | ||
| 86 | - self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.8]; | ||
| 87 | - self.userInteractionEnabled = NO; | ||
| 88 | - self.layer.cornerRadius = 7; | ||
| 89 | - | ||
| 90 | - [self addSubview:self.textLabel]; | ||
| 91 | - } | ||
| 92 | - return self; | ||
| 93 | -} | ||
| 94 | - | ||
| 95 | -- (void)updateConstraints { | ||
| 96 | - self.textLabel.translatesAutoresizingMaskIntoConstraints = NO; | ||
| 97 | - NSLayoutConstraint *layA = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1 constant:20]; | ||
| 98 | - NSLayoutConstraint *layB = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1 constant:-20]; | ||
| 99 | - NSLayoutConstraint *layC = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1 constant:-15]; | ||
| 100 | - NSLayoutConstraint *layD = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1 constant:70]; | ||
| 101 | - NSLayoutConstraint *layE = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:60]; | ||
| 102 | - [self addConstraints:@[layA, layB, layC, layD, layE]]; | ||
| 103 | - [super updateConstraints]; | ||
| 104 | -} | ||
| 105 | - | ||
| 106 | -- (void)layoutSubviews { | ||
| 107 | - [super layoutSubviews]; | ||
| 108 | - [self startAnimation]; | ||
| 109 | -} | ||
| 110 | - | ||
| 111 | -#pragma mark - animation | ||
| 112 | - | ||
| 113 | -- (void)showWithText:(NSString *)text type:(YBIBToastType)type { | ||
| 114 | - self.textLabel.text = text; | ||
| 115 | - _type = type; | ||
| 116 | - [self setNeedsLayout]; | ||
| 117 | -} | ||
| 118 | - | ||
| 119 | -- (void)startAnimation { | ||
| 120 | - if (_shapeLayer && _shapeLayer.superlayer) { | ||
| 121 | - [_shapeLayer removeFromSuperlayer]; | ||
| 122 | - } | ||
| 123 | - _shapeLayer = [CAShapeLayer layer]; | ||
| 124 | - _shapeLayer.strokeColor = [UIColor whiteColor].CGColor; | ||
| 125 | - _shapeLayer.fillColor = [UIColor clearColor].CGColor; | ||
| 126 | - _shapeLayer.lineWidth = 5.0; | ||
| 127 | - _shapeLayer.lineCap = @"round"; | ||
| 128 | - _shapeLayer.lineJoin = @"round"; | ||
| 129 | - _shapeLayer.strokeStart = 0.0; | ||
| 130 | - _shapeLayer.strokeEnd = 0.0; | ||
| 131 | - | ||
| 132 | - UIBezierPath *bezierPath = [UIBezierPath bezierPath]; | ||
| 133 | - CGFloat r = 13.0; | ||
| 134 | - CGFloat x = self.bounds.size.width / 2.0; | ||
| 135 | - CGFloat y = 38.0; | ||
| 136 | - switch (_type) { | ||
| 137 | - case YBIBToastTypeHook: { | ||
| 138 | - [bezierPath moveToPoint:CGPointMake(x - r - r / 2, y)]; | ||
| 139 | - [bezierPath addLineToPoint:CGPointMake(x - r / 2, y + r)]; | ||
| 140 | - [bezierPath addLineToPoint:CGPointMake(x + r * 2 - r / 2, y - r)]; | ||
| 141 | - } | ||
| 142 | - break; | ||
| 143 | - case YBIBToastTypeFork: { | ||
| 144 | - [bezierPath moveToPoint:CGPointMake(x - r, y - r)]; | ||
| 145 | - [bezierPath addLineToPoint:CGPointMake(x + r, y + r)]; | ||
| 146 | - [bezierPath moveToPoint:CGPointMake(x - r, y + r)]; | ||
| 147 | - [bezierPath addLineToPoint:CGPointMake(x + r, y - r)]; | ||
| 148 | - } | ||
| 149 | - break; | ||
| 150 | - default:break; | ||
| 151 | - } | ||
| 152 | - | ||
| 153 | - CABasicAnimation *baseAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; | ||
| 154 | - [baseAnimation setFromValue:@0.0]; | ||
| 155 | - [baseAnimation setToValue:@1.0]; | ||
| 156 | - [baseAnimation setDuration:0.3]; | ||
| 157 | - baseAnimation.removedOnCompletion = NO; | ||
| 158 | - baseAnimation.fillMode = kCAFillModeBoth; | ||
| 159 | - | ||
| 160 | - _shapeLayer.path = bezierPath.CGPath; | ||
| 161 | - [self.layer addSublayer:_shapeLayer]; | ||
| 162 | - [_shapeLayer addAnimation:baseAnimation forKey:@"strokeEnd"]; | ||
| 163 | -} | ||
| 164 | - | ||
| 165 | -#pragma mark - getter | ||
| 166 | - | ||
| 167 | -- (UILabel *)textLabel { | ||
| 168 | - if (!_textLabel) { | ||
| 169 | - _textLabel = [UILabel new]; | ||
| 170 | - _textLabel.textColor = [UIColor whiteColor]; | ||
| 171 | - _textLabel.font = [UIFont systemFontOfSize:14]; | ||
| 172 | - _textLabel.textAlignment = NSTextAlignmentCenter; | ||
| 173 | - _textLabel.numberOfLines = 0; | ||
| 174 | - } | ||
| 175 | - return _textLabel; | ||
| 176 | -} | ||
| 177 | - | ||
| 178 | -@end | ||
| 179 | - |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Base/NSObject+YBImageBrowser.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// NSObject+YBImageBrowser.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/9/26. | ||
| 6 | -// Copyright © 2019 杨波. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import <UIKit/UIKit.h> | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | -@interface NSObject (YBImageBrowser) | ||
| 14 | - | ||
| 15 | -@property (nonatomic, assign) CGFloat ybib_originAlpha; | ||
| 16 | - | ||
| 17 | -@end | ||
| 18 | - | ||
| 19 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Base/NSObject+YBImageBrowser.m deleted
100644 → 0
| 1 | -// | ||
| 2 | -// NSObject+YBImageBrowser.m | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/9/26. | ||
| 6 | -// Copyright © 2019 杨波. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "NSObject+YBImageBrowser.h" | ||
| 10 | -#import <objc/runtime.h> | ||
| 11 | - | ||
| 12 | -@implementation NSObject (YBImageBrowser) | ||
| 13 | - | ||
| 14 | -static void *YBIBOriginAlphaKey = &YBIBOriginAlphaKey; | ||
| 15 | -- (void)setYbib_originAlpha:(CGFloat)ybib_originAlpha { | ||
| 16 | - objc_setAssociatedObject(self, YBIBOriginAlphaKey, @(ybib_originAlpha), OBJC_ASSOCIATION_RETAIN_NONATOMIC); | ||
| 17 | -} | ||
| 18 | -- (CGFloat)ybib_originAlpha { | ||
| 19 | - NSNumber *alpha = objc_getAssociatedObject(self, YBIBOriginAlphaKey); | ||
| 20 | - return alpha ? alpha.floatValue : 1; | ||
| 21 | -} | ||
| 22 | - | ||
| 23 | -@end |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Base/YBIBAnimatedTransition.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBAnimatedTransition.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/6. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import <UIKit/UIKit.h> | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | -@protocol YBIBAnimatedTransition <NSObject> | ||
| 14 | -@required | ||
| 15 | - | ||
| 16 | -- (void)yb_showTransitioningWithContainer:(UIView *)container startView:(nullable __kindof UIView *)startView startImage:(nullable UIImage *)startImage endFrame:(CGRect)endFrame orientation:(UIDeviceOrientation)orientation completion:(void(^)(void))completion; | ||
| 17 | - | ||
| 18 | -- (void)yb_hideTransitioningWithContainer:(UIView *)container startView:(nullable __kindof UIView *)startView endView:(UIView *)endView orientation:(UIDeviceOrientation)orientation completion:(void(^)(void))completion; | ||
| 19 | - | ||
| 20 | -@end | ||
| 21 | - | ||
| 22 | - | ||
| 23 | -typedef NS_ENUM(NSInteger, YBIBTransitionType) { | ||
| 24 | - /// 无动效 | ||
| 25 | - YBIBTransitionTypeNone, | ||
| 26 | - /// 渐隐 | ||
| 27 | - YBIBTransitionTypeFade, | ||
| 28 | - /// 连贯移动 | ||
| 29 | - YBIBTransitionTypeCoherent | ||
| 30 | -}; | ||
| 31 | - | ||
| 32 | -@interface YBIBAnimatedTransition : NSObject <YBIBAnimatedTransition> | ||
| 33 | - | ||
| 34 | -/// 入场动效类型 | ||
| 35 | -@property (nonatomic, assign) YBIBTransitionType showType; | ||
| 36 | -/// 出场动效类型 | ||
| 37 | -@property (nonatomic, assign) YBIBTransitionType hideType; | ||
| 38 | - | ||
| 39 | -/// 入场动效持续时间 | ||
| 40 | -@property (nonatomic, assign) NSTimeInterval showDuration; | ||
| 41 | -/// 出场动效持续时间 | ||
| 42 | -@property (nonatomic, assign) NSTimeInterval hideDuration; | ||
| 43 | - | ||
| 44 | -@end | ||
| 45 | - | ||
| 46 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Base/YBIBAnimatedTransition.m deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBAnimatedTransition.m | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/6. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBAnimatedTransition.h" | ||
| 10 | - | ||
| 11 | -extern CGFloat YBIBRotationAngle(UIDeviceOrientation startOrientation, UIDeviceOrientation endOrientation); | ||
| 12 | - | ||
| 13 | -@implementation YBIBAnimatedTransition | ||
| 14 | - | ||
| 15 | -#pragma mark - life cycle | ||
| 16 | - | ||
| 17 | -- (instancetype)init { | ||
| 18 | - self = [super init]; | ||
| 19 | - if (self) { | ||
| 20 | - _showType = _hideType = YBIBTransitionTypeCoherent; | ||
| 21 | - _showDuration = _hideDuration = 0.25; | ||
| 22 | - } | ||
| 23 | - return self; | ||
| 24 | -} | ||
| 25 | - | ||
| 26 | -#pragma mark - <YBIBAnimationHandler> | ||
| 27 | - | ||
| 28 | -- (void)yb_showTransitioningWithContainer:(UIView *)container startView:(__kindof UIView *)startView startImage:(UIImage *)startImage endFrame:(CGRect)endFrame orientation:(UIDeviceOrientation)orientation completion:(void (^)(void))completion { | ||
| 29 | - YBIBTransitionType type = self.showType; | ||
| 30 | - if (type == YBIBTransitionTypeCoherent) { | ||
| 31 | - if (CGRectIsEmpty(endFrame) || !startView || orientation != (UIDeviceOrientation)UIApplication.sharedApplication.statusBarOrientation) { | ||
| 32 | - type = YBIBTransitionTypeFade; | ||
| 33 | - } | ||
| 34 | - } | ||
| 35 | - | ||
| 36 | - switch (type) { | ||
| 37 | - case YBIBTransitionTypeNone: { | ||
| 38 | - completion(); | ||
| 39 | - } | ||
| 40 | - break; | ||
| 41 | - case YBIBTransitionTypeFade: { | ||
| 42 | - | ||
| 43 | - BOOL animateValid = !CGRectIsEmpty(endFrame) && startView; | ||
| 44 | - | ||
| 45 | - UIImageView *animateImageView; | ||
| 46 | - if (animateValid) { | ||
| 47 | - animateImageView = [self imageViewAssimilateToView:startView]; | ||
| 48 | - animateImageView.frame = endFrame; | ||
| 49 | - animateImageView.image = startImage; | ||
| 50 | - [container addSubview:animateImageView]; | ||
| 51 | - } | ||
| 52 | - | ||
| 53 | - CGFloat rawAlpha = container.alpha; | ||
| 54 | - container.alpha = 0; | ||
| 55 | - | ||
| 56 | - if (!animateValid) completion(); | ||
| 57 | - | ||
| 58 | - [UIView animateWithDuration:self.showDuration animations:^{ | ||
| 59 | - container.alpha = rawAlpha; | ||
| 60 | - } completion:^(BOOL finished) { | ||
| 61 | - if (animateValid) { | ||
| 62 | - [animateImageView removeFromSuperview]; | ||
| 63 | - completion(); | ||
| 64 | - } | ||
| 65 | - }]; | ||
| 66 | - | ||
| 67 | - } | ||
| 68 | - break; | ||
| 69 | - case YBIBTransitionTypeCoherent: { | ||
| 70 | - | ||
| 71 | - UIImageView *animateImageView = [self imageViewAssimilateToView:startView]; | ||
| 72 | - animateImageView.frame = [startView convertRect:startView.bounds toView:container]; | ||
| 73 | - animateImageView.image = startImage; | ||
| 74 | - | ||
| 75 | - [container addSubview:animateImageView]; | ||
| 76 | - | ||
| 77 | - UIColor *rawBackgroundColor = container.backgroundColor; | ||
| 78 | - container.backgroundColor = [rawBackgroundColor colorWithAlphaComponent:0]; | ||
| 79 | - | ||
| 80 | - [UIView animateWithDuration:self.showDuration animations:^{ | ||
| 81 | - animateImageView.frame = endFrame; | ||
| 82 | - container.backgroundColor = rawBackgroundColor; | ||
| 83 | - } completion:^(BOOL finished) { | ||
| 84 | - completion(); | ||
| 85 | - // Disappear smoothly. | ||
| 86 | - [UIView animateWithDuration:0.2 animations:^{ | ||
| 87 | - animateImageView.alpha = 0; | ||
| 88 | - } completion:^(BOOL finished) { | ||
| 89 | - [animateImageView removeFromSuperview]; | ||
| 90 | - }]; | ||
| 91 | - }]; | ||
| 92 | - | ||
| 93 | - } | ||
| 94 | - break; | ||
| 95 | - } | ||
| 96 | -} | ||
| 97 | - | ||
| 98 | -- (void)yb_hideTransitioningWithContainer:(UIView *)container startView:(__kindof UIView *)startView endView:(UIView *)endView orientation:(UIDeviceOrientation)orientation completion:(void (^)(void))completion { | ||
| 99 | - YBIBTransitionType type = self.hideType; | ||
| 100 | - if (type == YBIBTransitionTypeCoherent && (!startView || !endView)) { | ||
| 101 | - type = YBIBTransitionTypeFade; | ||
| 102 | - } | ||
| 103 | - | ||
| 104 | - switch (type) { | ||
| 105 | - case YBIBTransitionTypeNone: { | ||
| 106 | - completion(); | ||
| 107 | - } | ||
| 108 | - break; | ||
| 109 | - case YBIBTransitionTypeFade: { | ||
| 110 | - | ||
| 111 | - CGFloat rawAlpha = container.alpha; | ||
| 112 | - | ||
| 113 | - [UIView animateWithDuration:self.hideDuration animations:^{ | ||
| 114 | - container.alpha = 0; | ||
| 115 | - } completion:^(BOOL finished) { | ||
| 116 | - completion(); | ||
| 117 | - container.alpha = rawAlpha; | ||
| 118 | - }]; | ||
| 119 | - | ||
| 120 | - } | ||
| 121 | - break; | ||
| 122 | - case YBIBTransitionTypeCoherent: { | ||
| 123 | - | ||
| 124 | - CGRect startFrame = startView.frame; | ||
| 125 | - CGRect endFrame = [endView convertRect:endView.bounds toView:startView.superview]; | ||
| 126 | - | ||
| 127 | - UIColor *rawBackgroundColor = container.backgroundColor; | ||
| 128 | - | ||
| 129 | - [UIView animateWithDuration:self.hideDuration animations:^{ | ||
| 130 | - | ||
| 131 | - container.backgroundColor = [rawBackgroundColor colorWithAlphaComponent:0]; | ||
| 132 | - | ||
| 133 | - startView.contentMode = endView.contentMode; | ||
| 134 | - | ||
| 135 | - CGAffineTransform transform = startView.transform; | ||
| 136 | - UIDeviceOrientation statusBarOrientation = (UIDeviceOrientation)UIApplication.sharedApplication.statusBarOrientation; | ||
| 137 | - if (orientation != statusBarOrientation) { | ||
| 138 | - transform = CGAffineTransformRotate(transform, YBIBRotationAngle(orientation, statusBarOrientation)); | ||
| 139 | - } | ||
| 140 | - | ||
| 141 | - if ([startView isKindOfClass:UIImageView.self]) { | ||
| 142 | - startView.frame = endFrame; | ||
| 143 | - startView.transform = transform; | ||
| 144 | - } else { | ||
| 145 | - CGFloat scale = MAX(endFrame.size.width / startFrame.size.width, endFrame.size.height / startFrame.size.height); | ||
| 146 | - startView.center = CGPointMake(endFrame.size.width * startView.layer.anchorPoint.x + endFrame.origin.x, endFrame.size.height * startView.layer.anchorPoint.y + endFrame.origin.y); | ||
| 147 | - startView.transform = CGAffineTransformScale(transform, scale, scale); | ||
| 148 | - } | ||
| 149 | - | ||
| 150 | - } completion:^(BOOL finished) { | ||
| 151 | - completion(); | ||
| 152 | - container.backgroundColor = rawBackgroundColor; | ||
| 153 | - }]; | ||
| 154 | - | ||
| 155 | - } | ||
| 156 | - break; | ||
| 157 | - } | ||
| 158 | -} | ||
| 159 | - | ||
| 160 | -#pragma mark - private | ||
| 161 | - | ||
| 162 | -- (UIImageView *)imageViewAssimilateToView:(nullable __kindof UIView *)view { | ||
| 163 | - UIImageView *animateImageView = [UIImageView new]; | ||
| 164 | - if ([view isKindOfClass:UIImageView.self]) { | ||
| 165 | - animateImageView.contentMode = view.contentMode; | ||
| 166 | - } else { | ||
| 167 | - animateImageView.contentMode = UIViewContentModeScaleAspectFill; | ||
| 168 | - } | ||
| 169 | - animateImageView.layer.masksToBounds = view.layer.masksToBounds; | ||
| 170 | - animateImageView.layer.cornerRadius = view.layer.cornerRadius; | ||
| 171 | - animateImageView.layer.backgroundColor = view.layer.backgroundColor; | ||
| 172 | - return animateImageView; | ||
| 173 | -} | ||
| 174 | - | ||
| 175 | -@end |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Base/YBIBCollectionView.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBCollectionView.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/6. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBCollectionViewLayout.h" | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | -@interface YBIBCollectionView : UICollectionView | ||
| 14 | - | ||
| 15 | -@property (nonatomic, strong, readonly) YBIBCollectionViewLayout *layout; | ||
| 16 | - | ||
| 17 | -- (NSString *)reuseIdentifierForCellClass:(Class)cellClass; | ||
| 18 | - | ||
| 19 | -- (nullable UICollectionViewCell *)centerCell; | ||
| 20 | - | ||
| 21 | -- (void)scrollToPage:(NSInteger)page; | ||
| 22 | - | ||
| 23 | -@end | ||
| 24 | - | ||
| 25 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Base/YBIBCollectionView.m deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBCollectionView.m | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/6. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBCollectionView.h" | ||
| 10 | - | ||
| 11 | -@implementation YBIBCollectionView { | ||
| 12 | - NSMutableSet *_reuseSet; | ||
| 13 | -} | ||
| 14 | - | ||
| 15 | -#pragma mark - life cycle | ||
| 16 | - | ||
| 17 | -- (instancetype)initWithFrame:(CGRect)frame { | ||
| 18 | - _layout = [YBIBCollectionViewLayout new]; | ||
| 19 | - return [self initWithFrame:frame collectionViewLayout:_layout]; | ||
| 20 | -} | ||
| 21 | - | ||
| 22 | -- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(nonnull UICollectionViewLayout *)layout { | ||
| 23 | - self = [super initWithFrame:frame collectionViewLayout:layout]; | ||
| 24 | - if (self) { | ||
| 25 | - self.backgroundColor = [UIColor clearColor]; | ||
| 26 | - self.pagingEnabled = YES; | ||
| 27 | - self.showsHorizontalScrollIndicator = NO; | ||
| 28 | - self.showsVerticalScrollIndicator = NO; | ||
| 29 | - self.alwaysBounceVertical = NO; | ||
| 30 | - self.alwaysBounceHorizontal = NO; | ||
| 31 | - self.decelerationRate = UIScrollViewDecelerationRateFast; | ||
| 32 | - if (@available(iOS 11.0, *)) { | ||
| 33 | - self.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; | ||
| 34 | - } | ||
| 35 | - _reuseSet = [NSMutableSet set]; | ||
| 36 | - } | ||
| 37 | - return self; | ||
| 38 | -} | ||
| 39 | - | ||
| 40 | -#pragma mark - public | ||
| 41 | - | ||
| 42 | -- (NSString *)reuseIdentifierForCellClass:(Class)cellClass { | ||
| 43 | - NSString *identifier = NSStringFromClass(cellClass); | ||
| 44 | - if (![_reuseSet containsObject:identifier]) { | ||
| 45 | - NSString *path = [[NSBundle mainBundle] pathForResource:identifier ofType:@"nib"]; | ||
| 46 | - if (path) { | ||
| 47 | - [self registerNib:[UINib nibWithNibName:identifier bundle:nil] forCellWithReuseIdentifier:identifier]; | ||
| 48 | - } else { | ||
| 49 | - [self registerClass:cellClass forCellWithReuseIdentifier:identifier]; | ||
| 50 | - } | ||
| 51 | - [_reuseSet addObject:identifier]; | ||
| 52 | - } | ||
| 53 | - return identifier; | ||
| 54 | -} | ||
| 55 | - | ||
| 56 | -- (UICollectionViewCell *)centerCell { | ||
| 57 | - NSArray<UICollectionViewCell *> *cells = [self visibleCells]; | ||
| 58 | - if (cells.count == 0) return nil; | ||
| 59 | - | ||
| 60 | - UICollectionViewCell *res = cells[0]; | ||
| 61 | - CGFloat centerX = self.contentOffset.x + (self.bounds.size.width / 2.0); | ||
| 62 | - for (int i = 1; i < cells.count; ++i) { | ||
| 63 | - if (ABS(cells[i].center.x - centerX) < ABS(res.center.x - centerX)) { | ||
| 64 | - res = cells[i]; | ||
| 65 | - } | ||
| 66 | - } | ||
| 67 | - return res; | ||
| 68 | -} | ||
| 69 | - | ||
| 70 | -- (void)scrollToPage:(NSInteger)page { | ||
| 71 | - [self setContentOffset:CGPointMake(self.bounds.size.width * page, 0)]; | ||
| 72 | -} | ||
| 73 | - | ||
| 74 | -#pragma mark - hit test | ||
| 75 | - | ||
| 76 | -- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { | ||
| 77 | - UIView *view = [super hitTest:point withEvent:event]; | ||
| 78 | - // When the hit-test view is 'UISlider', set '_scrollEnabled' to 'NO', avoid gesture conflicts. | ||
| 79 | - self.scrollEnabled = ![view isKindOfClass:UISlider.class]; | ||
| 80 | - return view; | ||
| 81 | -} | ||
| 82 | - | ||
| 83 | -@end |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Base/YBIBCollectionViewLayout.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBCollectionViewLayout.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 杨少 on 2018/4/17. | ||
| 6 | -// Copyright © 2018年 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import <UIKit/UIKit.h> | ||
| 10 | - | ||
| 11 | -@interface YBIBCollectionViewLayout : UICollectionViewFlowLayout | ||
| 12 | - | ||
| 13 | -@property (nonatomic, assign) CGFloat distanceBetweenPages; | ||
| 14 | - | ||
| 15 | -@end | ||
| 16 | - |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Base/YBIBCollectionViewLayout.m deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBCollectionViewLayout.m | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 杨少 on 2018/4/17. | ||
| 6 | -// Copyright © 2018年 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBCollectionViewLayout.h" | ||
| 10 | - | ||
| 11 | -@implementation YBIBCollectionViewLayout | ||
| 12 | - | ||
| 13 | -- (instancetype)init { | ||
| 14 | - self = [super init]; | ||
| 15 | - if (self) { | ||
| 16 | - self.minimumLineSpacing = 0; | ||
| 17 | - self.minimumInteritemSpacing = 0; | ||
| 18 | - self.sectionInset = UIEdgeInsetsZero; | ||
| 19 | - self.scrollDirection = UICollectionViewScrollDirectionHorizontal; | ||
| 20 | - _distanceBetweenPages = 20; | ||
| 21 | - } | ||
| 22 | - return self; | ||
| 23 | -} | ||
| 24 | - | ||
| 25 | -- (void)prepareLayout { | ||
| 26 | - [super prepareLayout]; | ||
| 27 | - self.itemSize = self.collectionView.bounds.size; | ||
| 28 | -} | ||
| 29 | - | ||
| 30 | -- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect { | ||
| 31 | - NSArray<UICollectionViewLayoutAttributes *> *layoutAttsArray = [[NSArray alloc] initWithArray:[super layoutAttributesForElementsInRect:rect] copyItems:YES]; | ||
| 32 | - CGFloat halfWidth = self.collectionView.bounds.size.width / 2.0; | ||
| 33 | - CGFloat centerX = self.collectionView.contentOffset.x + halfWidth; | ||
| 34 | - [layoutAttsArray enumerateObjectsUsingBlock:^(UICollectionViewLayoutAttributes * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { | ||
| 35 | - obj.center = CGPointMake(obj.center.x + (obj.center.x - centerX) / halfWidth * self.distanceBetweenPages / 2, obj.center.y); | ||
| 36 | - }]; | ||
| 37 | - return layoutAttsArray; | ||
| 38 | -} | ||
| 39 | - | ||
| 40 | -- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { | ||
| 41 | - return YES; | ||
| 42 | -} | ||
| 43 | - | ||
| 44 | -@end |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Base/YBIBContainerView.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBContainerView.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/7/11. | ||
| 6 | -// Copyright © 2019 杨波. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import <UIKit/UIKit.h> | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | -@interface YBIBContainerView : UIView | ||
| 14 | - | ||
| 15 | -@end | ||
| 16 | - | ||
| 17 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Base/YBIBContainerView.m deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBContainerView.m | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/7/11. | ||
| 6 | -// Copyright © 2019 杨波. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBContainerView.h" | ||
| 10 | - | ||
| 11 | -@implementation YBIBContainerView | ||
| 12 | - | ||
| 13 | -- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { | ||
| 14 | - UIView *originView = [super hitTest:point withEvent:event]; | ||
| 15 | - if ([originView isKindOfClass:self.class]) { | ||
| 16 | - // Continue hit-testing if the view is kind of 'self.class'. | ||
| 17 | - return nil; | ||
| 18 | - } | ||
| 19 | - return originView; | ||
| 20 | -} | ||
| 21 | - | ||
| 22 | -@end |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Base/YBIBDataMediator.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBDataMediator.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/6. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBImageBrowser.h" | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | -@interface YBIBDataMediator : NSObject | ||
| 14 | - | ||
| 15 | -- (instancetype)initWithBrowser:(YBImageBrowser *)browser; | ||
| 16 | - | ||
| 17 | -@property (nonatomic, assign) NSUInteger dataCacheCountLimit; | ||
| 18 | - | ||
| 19 | -- (NSInteger)numberOfCells; | ||
| 20 | - | ||
| 21 | -- (id<YBIBDataProtocol>)dataForCellAtIndex:(NSInteger)index; | ||
| 22 | - | ||
| 23 | -- (void)clear; | ||
| 24 | - | ||
| 25 | -@property (nonatomic, assign) NSUInteger preloadCount; | ||
| 26 | - | ||
| 27 | -- (void)preloadWithPage:(NSInteger)page; | ||
| 28 | - | ||
| 29 | -@end | ||
| 30 | - | ||
| 31 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Base/YBIBDataMediator.m deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBDataMediator.m | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/6. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBDataMediator.h" | ||
| 10 | -#import "YBImageBrowser+Internal.h" | ||
| 11 | - | ||
| 12 | -@implementation YBIBDataMediator { | ||
| 13 | - __weak YBImageBrowser *_browser; | ||
| 14 | - NSCache<NSNumber *, id<YBIBDataProtocol>> *_dataCache; | ||
| 15 | -} | ||
| 16 | - | ||
| 17 | -#pragma mark - life cycle | ||
| 18 | - | ||
| 19 | -- (instancetype)initWithBrowser:(YBImageBrowser *)browser { | ||
| 20 | - if (self = [super init]) { | ||
| 21 | - _browser = browser; | ||
| 22 | - _dataCache = [NSCache new]; | ||
| 23 | - } | ||
| 24 | - return self; | ||
| 25 | -} | ||
| 26 | - | ||
| 27 | -#pragma mark - public | ||
| 28 | - | ||
| 29 | -- (NSInteger)numberOfCells { | ||
| 30 | - return _browser.dataSource ? [_browser.dataSource yb_numberOfCellsInImageBrowser:_browser] : _browser.dataSourceArray.count; | ||
| 31 | -} | ||
| 32 | - | ||
| 33 | -- (id<YBIBDataProtocol>)dataForCellAtIndex:(NSInteger)index { | ||
| 34 | - if (index < 0 || index > self.numberOfCells - 1) return nil; | ||
| 35 | - | ||
| 36 | - id<YBIBDataProtocol> data = [_dataCache objectForKey:@(index)]; | ||
| 37 | - if (!data) { | ||
| 38 | - data = _browser.dataSource ? [_browser.dataSource yb_imageBrowser:_browser dataForCellAtIndex:index] : _browser.dataSourceArray[index]; | ||
| 39 | - [_dataCache setObject:data forKey:@(index)]; | ||
| 40 | - [_browser implementGetBaseInfoProtocol:data]; | ||
| 41 | - } | ||
| 42 | - return data; | ||
| 43 | -} | ||
| 44 | - | ||
| 45 | -- (void)clear { | ||
| 46 | - [_dataCache removeAllObjects]; | ||
| 47 | -} | ||
| 48 | - | ||
| 49 | -- (void)preloadWithPage:(NSInteger)page { | ||
| 50 | - if (_preloadCount == 0) return; | ||
| 51 | - | ||
| 52 | - NSInteger left = -(_preloadCount / 2), right = _preloadCount - ABS(left); | ||
| 53 | - for (NSInteger i = left; i <= right; ++i) { | ||
| 54 | - if (i == 0) continue; | ||
| 55 | - id<YBIBDataProtocol> targetData = [self dataForCellAtIndex:page + i]; | ||
| 56 | - if ([targetData respondsToSelector:@selector(yb_preload)]) { | ||
| 57 | - [targetData yb_preload]; | ||
| 58 | - } | ||
| 59 | - } | ||
| 60 | -} | ||
| 61 | - | ||
| 62 | -#pragma mark - getters & setters | ||
| 63 | - | ||
| 64 | -- (void)setDataCacheCountLimit:(NSUInteger)dataCacheCountLimit { | ||
| 65 | - _dataCacheCountLimit = dataCacheCountLimit; | ||
| 66 | - _dataCache.countLimit = dataCacheCountLimit; | ||
| 67 | -} | ||
| 68 | - | ||
| 69 | -@end |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Base/YBIBScreenRotationHandler.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBScreenRotationHandler.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/8. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBImageBrowser.h" | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | -@interface YBIBScreenRotationHandler : NSObject | ||
| 14 | - | ||
| 15 | -- (instancetype)initWithBrowser:(YBImageBrowser *)browser; | ||
| 16 | - | ||
| 17 | -- (void)startObserveStatusBarOrientation; | ||
| 18 | - | ||
| 19 | -- (void)startObserveDeviceOrientation; | ||
| 20 | - | ||
| 21 | -- (void)clear; | ||
| 22 | - | ||
| 23 | -- (void)configContainerSize:(CGSize)size; | ||
| 24 | - | ||
| 25 | -- (CGSize)containerSizeWithOrientation:(UIDeviceOrientation)orientation; | ||
| 26 | - | ||
| 27 | -@property (nonatomic, assign, readonly, getter=isRotating) BOOL rotating; | ||
| 28 | - | ||
| 29 | -@property (nonatomic, assign, readonly) UIDeviceOrientation currentOrientation; | ||
| 30 | - | ||
| 31 | -@property (nonatomic, assign) UIInterfaceOrientationMask supportedOrientations; | ||
| 32 | - | ||
| 33 | -@property (nonatomic, assign) NSTimeInterval rotationDuration; | ||
| 34 | - | ||
| 35 | -@end | ||
| 36 | - | ||
| 37 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Base/YBIBScreenRotationHandler.m deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBScreenRotationHandler.m | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/8. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBScreenRotationHandler.h" | ||
| 10 | -#import "YBIBUtilities.h" | ||
| 11 | -#import "YBIBCellProtocol.h" | ||
| 12 | -#import "YBImageBrowser+Internal.h" | ||
| 13 | - | ||
| 14 | -BOOL YBIBValidDeviceOrientation(UIDeviceOrientation orientation) { | ||
| 15 | - static NSSet *validSet; | ||
| 16 | - static dispatch_once_t onceToken; | ||
| 17 | - dispatch_once(&onceToken, ^{ | ||
| 18 | - validSet = [NSSet setWithObjects:@(UIDeviceOrientationPortrait), @(UIDeviceOrientationPortraitUpsideDown), @(UIDeviceOrientationLandscapeLeft), @(UIDeviceOrientationLandscapeRight), nil]; | ||
| 19 | - }); | ||
| 20 | - return [validSet containsObject:@(orientation)]; | ||
| 21 | -} | ||
| 22 | - | ||
| 23 | -CGFloat YBIBRotationAngle(UIDeviceOrientation startOrientation, UIDeviceOrientation endOrientation) { | ||
| 24 | - static NSDictionary<NSNumber*, NSNumber*> *angleMap; | ||
| 25 | - static dispatch_once_t onceToken; | ||
| 26 | - dispatch_once(&onceToken, ^{ | ||
| 27 | - angleMap = @{@(UIDeviceOrientationPortrait):@(0), @(UIDeviceOrientationPortraitUpsideDown):@(M_PI), @(UIDeviceOrientationLandscapeLeft):@(M_PI_2), @(UIDeviceOrientationLandscapeRight): @(-M_PI_2)}; | ||
| 28 | - }); | ||
| 29 | - NSNumber *start = angleMap[@(startOrientation)], *end = angleMap[@(endOrientation)]; | ||
| 30 | - CGFloat res = CGFLOAT_IS_DOUBLE ? end.doubleValue - start.doubleValue : end.floatValue - start.floatValue; | ||
| 31 | - if (ABS(res) > M_PI) { | ||
| 32 | - return res > 0 ? res - M_PI * 2 : M_PI * 2 + res; | ||
| 33 | - } | ||
| 34 | - return res; | ||
| 35 | -} | ||
| 36 | - | ||
| 37 | - | ||
| 38 | -static NSUInteger const kMaskNull = 10000; | ||
| 39 | - | ||
| 40 | -@interface YBIBScreenRotationHandler () | ||
| 41 | -@property (nonatomic, assign) BOOL rotating; | ||
| 42 | -@property (nonatomic, assign) UIDeviceOrientation currentOrientation; | ||
| 43 | -@end | ||
| 44 | - | ||
| 45 | -@implementation YBIBScreenRotationHandler { | ||
| 46 | - __weak YBImageBrowser *_browser; | ||
| 47 | - CGSize _verticalContainerSize; | ||
| 48 | - CGSize _horizontalContainerSize; | ||
| 49 | - NSInteger _recordPage; | ||
| 50 | -} | ||
| 51 | - | ||
| 52 | -#pragma mark - life cycle | ||
| 53 | - | ||
| 54 | -- (void)dealloc { | ||
| 55 | - [self clear]; | ||
| 56 | -} | ||
| 57 | - | ||
| 58 | -- (instancetype)initWithBrowser:(YBImageBrowser *)browser { | ||
| 59 | - if (self = [super init]) { | ||
| 60 | - _browser = browser; | ||
| 61 | - _rotating = NO; | ||
| 62 | - _supportedOrientations = UIInterfaceOrientationMaskAllButUpsideDown; | ||
| 63 | - _rotationDuration = 0.25; | ||
| 64 | - } | ||
| 65 | - return self; | ||
| 66 | -} | ||
| 67 | - | ||
| 68 | -#pragma mark - public | ||
| 69 | - | ||
| 70 | -- (void)startObserveStatusBarOrientation { | ||
| 71 | - self.currentOrientation = (UIDeviceOrientation)UIApplication.sharedApplication.statusBarOrientation; | ||
| 72 | - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidChangedStatusBarOrientationNotification:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; | ||
| 73 | - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillChangeStatusBarOrientationNotification:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil]; | ||
| 74 | -} | ||
| 75 | - | ||
| 76 | -- (void)startObserveDeviceOrientation { | ||
| 77 | - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChangeNotification:) name:UIDeviceOrientationDidChangeNotification object:nil]; | ||
| 78 | -} | ||
| 79 | - | ||
| 80 | -- (void)clear { | ||
| 81 | - [[NSNotificationCenter defaultCenter] removeObserver:self]; | ||
| 82 | -} | ||
| 83 | - | ||
| 84 | -- (void)configContainerSize:(CGSize)size { | ||
| 85 | - if (UIDeviceOrientationIsLandscape(self.currentOrientation)) { | ||
| 86 | - // Now is horizontal. | ||
| 87 | - _verticalContainerSize = CGSizeMake(size.height, size.width); | ||
| 88 | - _horizontalContainerSize = size; | ||
| 89 | - } else { | ||
| 90 | - // Now is vertical. | ||
| 91 | - _verticalContainerSize = size; | ||
| 92 | - _horizontalContainerSize = CGSizeMake(size.height, size.width); | ||
| 93 | - } | ||
| 94 | -} | ||
| 95 | - | ||
| 96 | -- (CGSize)containerSizeWithOrientation:(UIDeviceOrientation)orientation { | ||
| 97 | - return UIDeviceOrientationIsLandscape(orientation) ? _horizontalContainerSize : _verticalContainerSize; | ||
| 98 | -} | ||
| 99 | - | ||
| 100 | -#pragma mark - private | ||
| 101 | - | ||
| 102 | -- (BOOL)supportedOfOrientation:(UIDeviceOrientation)orientation { | ||
| 103 | - if (!YBIBValidDeviceOrientation(orientation)) return NO; | ||
| 104 | - NSMutableSet *set = [NSMutableSet set]; | ||
| 105 | - if (_supportedOrientations & UIInterfaceOrientationMaskPortrait) [set addObject:@(UIDeviceOrientationPortrait)]; | ||
| 106 | - if (_supportedOrientations & UIInterfaceOrientationMaskPortraitUpsideDown) [set addObject:@(UIDeviceOrientationPortraitUpsideDown)]; | ||
| 107 | - if (_supportedOrientations & UIInterfaceOrientationMaskLandscapeRight) [set addObject:@(UIDeviceOrientationLandscapeLeft)]; | ||
| 108 | - if (_supportedOrientations & UIInterfaceOrientationMaskLandscapeLeft) [set addObject:@(UIDeviceOrientationLandscapeRight)]; | ||
| 109 | - return [set containsObject:@(orientation)]; | ||
| 110 | -} | ||
| 111 | - | ||
| 112 | -- (BOOL)supportedOnlyOneSystemOrientation { | ||
| 113 | - UIInterfaceOrientationMask mask = [self supportSystemOrientationMask]; | ||
| 114 | - return mask == (mask & (-mask)); | ||
| 115 | -} | ||
| 116 | - | ||
| 117 | -- (void)orientationWillChangeWithExpectOrientation:(UIDeviceOrientation)orientation centerCell:(UICollectionViewCell<YBIBCellProtocol> *)centerCell { | ||
| 118 | - if ([centerCell respondsToSelector:@selector(yb_orientationWillChangeWithExpectOrientation:)]) { | ||
| 119 | - [centerCell yb_orientationWillChangeWithExpectOrientation:orientation]; | ||
| 120 | - } | ||
| 121 | - for (id<YBIBToolViewHandler> handler in _browser.toolViewHandlers) { | ||
| 122 | - if ([handler respondsToSelector:@selector(yb_orientationWillChangeWithExpectOrientation:)]) { | ||
| 123 | - [handler yb_orientationWillChangeWithExpectOrientation:orientation]; | ||
| 124 | - } | ||
| 125 | - } | ||
| 126 | -} | ||
| 127 | - | ||
| 128 | -- (void)orientationChangeAnimationWithExpectOrientation:(UIDeviceOrientation)orientation centerCell:(UICollectionViewCell<YBIBCellProtocol> *)centerCell { | ||
| 129 | - if ([centerCell respondsToSelector:@selector(yb_orientationChangeAnimationWithExpectOrientation:)]) { | ||
| 130 | - [centerCell yb_orientationChangeAnimationWithExpectOrientation:orientation]; | ||
| 131 | - [centerCell layoutIfNeeded]; // Compatible with autolayout. | ||
| 132 | - } | ||
| 133 | - for (id<YBIBToolViewHandler> handler in _browser.toolViewHandlers) { | ||
| 134 | - if ([handler respondsToSelector:@selector(yb_orientationChangeAnimationWithExpectOrientation:)]) { | ||
| 135 | - [handler yb_orientationChangeAnimationWithExpectOrientation:orientation]; | ||
| 136 | - } | ||
| 137 | - } | ||
| 138 | -} | ||
| 139 | - | ||
| 140 | -- (void)orientationDidChangedWithOrientation:(UIDeviceOrientation)orientation centerCell:(UICollectionViewCell<YBIBCellProtocol> *)centerCell { | ||
| 141 | - if ([centerCell respondsToSelector:@selector(yb_orientationDidChangedWithOrientation:)]) { | ||
| 142 | - [centerCell yb_orientationDidChangedWithOrientation:orientation]; | ||
| 143 | - } | ||
| 144 | - for (id<YBIBToolViewHandler> handler in _browser.toolViewHandlers) { | ||
| 145 | - if ([handler respondsToSelector:@selector(yb_orientationDidChangedWithOrientation:)]) { | ||
| 146 | - [handler yb_orientationDidChangedWithOrientation:orientation]; | ||
| 147 | - } | ||
| 148 | - } | ||
| 149 | -} | ||
| 150 | - | ||
| 151 | -#pragma mark - event | ||
| 152 | - | ||
| 153 | -- (void)deviceOrientationDidChangeNotification:(NSNotification *)note { | ||
| 154 | - if (![self supportedOnlyOneSystemOrientation]) return; | ||
| 155 | - if (_browser.isTransitioning || self.rotating) return; | ||
| 156 | - | ||
| 157 | - UIDeviceOrientation expectOrientation = [UIDevice currentDevice].orientation; | ||
| 158 | - if (expectOrientation == self.currentOrientation || ![self supportedOfOrientation:expectOrientation]) return; | ||
| 159 | - | ||
| 160 | - self.rotating = YES; | ||
| 161 | - | ||
| 162 | - // Align. | ||
| 163 | - [_browser.collectionView scrollToPage:_browser.currentPage]; | ||
| 164 | - // Record current page number before transforming. | ||
| 165 | - NSInteger currentPage = _browser.currentPage; | ||
| 166 | - | ||
| 167 | - UIDeviceOrientation statusBarOrientation = (UIDeviceOrientation)UIApplication.sharedApplication.statusBarOrientation; | ||
| 168 | - CGFloat angleStatusBarToExpect = YBIBRotationAngle(statusBarOrientation, expectOrientation); | ||
| 169 | - CGFloat angleCurrentToExpect = YBIBRotationAngle(_currentOrientation, expectOrientation); | ||
| 170 | - CGRect expectBounds = (CGRect){CGPointZero, [self containerSizeWithOrientation:expectOrientation]}; | ||
| 171 | - UICollectionViewCell<YBIBCellProtocol> *centerCell = (UICollectionViewCell<YBIBCellProtocol> *)self->_browser.collectionView.centerCell; | ||
| 172 | - // Animate smoothly if bigger rotation angle. | ||
| 173 | - NSTimeInterval duration = self.rotationDuration * (ABS(angleCurrentToExpect) > M_PI_2 ? 2 : 1); | ||
| 174 | - | ||
| 175 | - // 'collectionView' transformation. | ||
| 176 | - self->_browser.collectionView.bounds = expectBounds; | ||
| 177 | - self->_browser.collectionView.transform = CGAffineTransformMakeRotation(angleStatusBarToExpect); | ||
| 178 | - centerCell.contentView.transform = CGAffineTransformMakeRotation(-angleCurrentToExpect); | ||
| 179 | - | ||
| 180 | - // Reset to prevent the page number change after transforming. | ||
| 181 | - [self->_browser.collectionView scrollToPage:currentPage]; | ||
| 182 | - | ||
| 183 | - [self orientationWillChangeWithExpectOrientation:expectOrientation centerCell:centerCell]; | ||
| 184 | - | ||
| 185 | - [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ | ||
| 186 | - | ||
| 187 | - // Maybe the internal UI need to transform. | ||
| 188 | - [self orientationChangeAnimationWithExpectOrientation:expectOrientation centerCell:centerCell]; | ||
| 189 | - | ||
| 190 | - centerCell.contentView.bounds = expectBounds; | ||
| 191 | - centerCell.contentView.transform = CGAffineTransformIdentity; | ||
| 192 | - | ||
| 193 | - self->_browser.containerView.bounds = expectBounds; | ||
| 194 | - self->_browser.containerView.transform = CGAffineTransformMakeRotation(angleStatusBarToExpect); | ||
| 195 | - | ||
| 196 | - } completion:^(BOOL finished) { | ||
| 197 | - self.currentOrientation = expectOrientation; | ||
| 198 | - self.rotating = NO; | ||
| 199 | - | ||
| 200 | - [self orientationDidChangedWithOrientation:expectOrientation centerCell:centerCell]; | ||
| 201 | - }]; | ||
| 202 | -} | ||
| 203 | - | ||
| 204 | -- (void)applicationWillChangeStatusBarOrientationNotification:(NSNotification *)noti { | ||
| 205 | - if ([self supportedOnlyOneSystemOrientation]) return; | ||
| 206 | - | ||
| 207 | - self.rotating = YES; | ||
| 208 | - // Record current page number before transforming. | ||
| 209 | - _recordPage = _browser.currentPage; | ||
| 210 | - | ||
| 211 | - UICollectionViewCell<YBIBCellProtocol> *centerCell = (UICollectionViewCell<YBIBCellProtocol> *)self->_browser.collectionView.centerCell; | ||
| 212 | - UIDeviceOrientation expectOrientation = ((NSNumber *)noti.userInfo[UIApplicationStatusBarOrientationUserInfoKey]).integerValue; | ||
| 213 | - [self orientationWillChangeWithExpectOrientation:expectOrientation centerCell:centerCell]; | ||
| 214 | -} | ||
| 215 | - | ||
| 216 | -- (void)applicationDidChangedStatusBarOrientationNotification:(NSNotification *)noti { | ||
| 217 | - if ([self supportedOnlyOneSystemOrientation]) return; | ||
| 218 | - | ||
| 219 | - UIDeviceOrientation expectOrientation = (UIDeviceOrientation)UIApplication.sharedApplication.statusBarOrientation; | ||
| 220 | - UICollectionViewCell<YBIBCellProtocol> *centerCell = (UICollectionViewCell<YBIBCellProtocol> *)self->_browser.collectionView.centerCell; | ||
| 221 | - | ||
| 222 | - [self orientationChangeAnimationWithExpectOrientation:expectOrientation centerCell:centerCell]; | ||
| 223 | - | ||
| 224 | - CGRect expectBounds = (CGRect){CGPointZero, [self containerSizeWithOrientation:expectOrientation]}; | ||
| 225 | - self->_browser.collectionView.layout.itemSize = expectBounds.size; | ||
| 226 | - | ||
| 227 | - // Reset to prevent the page number change after transforming. | ||
| 228 | - [_browser.collectionView scrollToPage:_recordPage]; | ||
| 229 | - | ||
| 230 | - self.currentOrientation = expectOrientation; | ||
| 231 | - self.rotating = NO; | ||
| 232 | - | ||
| 233 | - [self orientationDidChangedWithOrientation:expectOrientation centerCell:centerCell]; | ||
| 234 | -} | ||
| 235 | - | ||
| 236 | -#pragma mark - getters & setters | ||
| 237 | - | ||
| 238 | -- (void)setRotating:(BOOL)rotating { | ||
| 239 | - _rotating = rotating; | ||
| 240 | - _browser.containerView.userInteractionEnabled = !rotating; | ||
| 241 | - _browser.collectionView.userInteractionEnabled = !rotating; | ||
| 242 | - _browser.collectionView.panGestureRecognizer.enabled = !rotating; | ||
| 243 | -} | ||
| 244 | - | ||
| 245 | -#pragma mark - calculate supported orientation of system | ||
| 246 | - | ||
| 247 | -- (UIInterfaceOrientationMask)supportSystemOrientationMask { | ||
| 248 | - UIInterfaceOrientationMask limitMask = 0; | ||
| 249 | - // IphoneX series do not support UIInterfaceOrientationMaskPortraitUpsideDown, except selector '-application:supportedInterfaceOrientationsForWindow:' of '[UIApplication sharedApplication].delegate' return 0. Maybe it is BUG of Apple. | ||
| 250 | - BOOL ignoreUpsideDownIfIphoneX = YES; | ||
| 251 | - UIInterfaceOrientationMask delegateMask = [self maskOfApplicationDelegate]; | ||
| 252 | - if (delegateMask != kMaskNull) { | ||
| 253 | - if (delegateMask == 0) { | ||
| 254 | - // Apple do. | ||
| 255 | - limitMask = UIInterfaceOrientationMaskAll; | ||
| 256 | - ignoreUpsideDownIfIphoneX = NO; | ||
| 257 | - } else { | ||
| 258 | - limitMask = delegateMask; | ||
| 259 | - } | ||
| 260 | - } else { | ||
| 261 | - // Lower priority. | ||
| 262 | - limitMask = [self maskOfInfoPlist]; | ||
| 263 | - } | ||
| 264 | - | ||
| 265 | - UIInterfaceOrientationMask supportMask = limitMask & [self maskOfViewController]; | ||
| 266 | - | ||
| 267 | - if (ignoreUpsideDownIfIphoneX && YBIBIsIphoneXSeries() && (supportMask & UIInterfaceOrientationMaskPortraitUpsideDown)) { | ||
| 268 | - supportMask ^= UIInterfaceOrientationMaskPortraitUpsideDown; | ||
| 269 | - } | ||
| 270 | - return supportMask; | ||
| 271 | -} | ||
| 272 | - | ||
| 273 | -- (UIInterfaceOrientationMask)maskOfInfoPlist { | ||
| 274 | - // 'Info.plist' will not change in a process. | ||
| 275 | - static UIInterfaceOrientationMask mask = 0; | ||
| 276 | - static dispatch_once_t onceToken; | ||
| 277 | - dispatch_once(&onceToken, ^{ | ||
| 278 | - NSString *path = [[NSBundle mainBundle] pathForResource:@"Info" ofType:@"plist"]; | ||
| 279 | - NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithContentsOfFile:path]; | ||
| 280 | - NSArray *array = dict[@"UISupportedInterfaceOrientations"]; | ||
| 281 | - NSSet *set = [NSSet setWithArray:array]; | ||
| 282 | - if ([set containsObject:@"UIInterfaceOrientationPortrait"]) mask |= UIInterfaceOrientationMaskPortrait; | ||
| 283 | - if ([set containsObject:@"UIInterfaceOrientationLandscapeRight"]) mask |= UIInterfaceOrientationMaskLandscapeRight; | ||
| 284 | - if ([set containsObject:@"UIInterfaceOrientationLandscapeLeft"]) mask |= UIInterfaceOrientationMaskLandscapeLeft; | ||
| 285 | - if ([set containsObject:@"UIInterfaceOrientationPortraitUpsideDown"]) mask |= UIInterfaceOrientationMaskPortraitUpsideDown; | ||
| 286 | - }); | ||
| 287 | - return mask == 0 ? kMaskNull : mask; | ||
| 288 | -} | ||
| 289 | - | ||
| 290 | -- (UIInterfaceOrientationMask)maskOfApplicationDelegate { | ||
| 291 | - UIInterfaceOrientationMask mask = kMaskNull; | ||
| 292 | - id<UIApplicationDelegate> delegate = [UIApplication sharedApplication].delegate; | ||
| 293 | - if ([delegate respondsToSelector:@selector(application:supportedInterfaceOrientationsForWindow:)]) { | ||
| 294 | - mask = [delegate application:[UIApplication sharedApplication] supportedInterfaceOrientationsForWindow:_browser.window]; | ||
| 295 | - } | ||
| 296 | - return mask; | ||
| 297 | -} | ||
| 298 | - | ||
| 299 | -- (UIInterfaceOrientationMask)maskOfViewController { | ||
| 300 | - UIInterfaceOrientationMask mask = kMaskNull; | ||
| 301 | - | ||
| 302 | - // Find the UIViewController whitch 'browser' followed. | ||
| 303 | - UIViewController *target = nil; | ||
| 304 | - id next = _browser; | ||
| 305 | - while (next) { | ||
| 306 | - if ([next isKindOfClass:UIViewController.self]) { | ||
| 307 | - target = next; | ||
| 308 | - break; | ||
| 309 | - } | ||
| 310 | - if ([next isKindOfClass:UIWindow.self]) { | ||
| 311 | - target = YBIBTopControllerByWindow(next); | ||
| 312 | - break; | ||
| 313 | - } | ||
| 314 | - next = [next nextResponder]; | ||
| 315 | - } | ||
| 316 | - | ||
| 317 | - // Cover directly. | ||
| 318 | - if (target.tabBarController) { | ||
| 319 | - mask = target.tabBarController.shouldAutorotate ? target.tabBarController.supportedInterfaceOrientations : 0; | ||
| 320 | - } else if (target.navigationController) { | ||
| 321 | - mask = target.navigationController.shouldAutorotate ? target.navigationController.supportedInterfaceOrientations : 0; | ||
| 322 | - } else { | ||
| 323 | - mask = target.shouldAutorotate ? target.supportedInterfaceOrientations : 0; | ||
| 324 | - } | ||
| 325 | - return mask; | ||
| 326 | -} | ||
| 327 | - | ||
| 328 | -@end |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Base/YBImageBrowser+Internal.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBImageBrowser+Internal.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/7/1. | ||
| 6 | -// Copyright © 2019 杨波. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBImageBrowser.h" | ||
| 10 | -#import "YBIBContainerView.h" | ||
| 11 | - | ||
| 12 | -NS_ASSUME_NONNULL_BEGIN | ||
| 13 | - | ||
| 14 | -@interface YBImageBrowser () | ||
| 15 | - | ||
| 16 | -@property (nonatomic, strong) YBIBContainerView *containerView; | ||
| 17 | - | ||
| 18 | -- (void)implementGetBaseInfoProtocol:(id<YBIBGetBaseInfoProtocol>)obj; | ||
| 19 | - | ||
| 20 | -@property (nonatomic, weak, nullable) NSObject *hiddenProjectiveView; | ||
| 21 | - | ||
| 22 | -@end | ||
| 23 | - | ||
| 24 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Helper/YBIBCopywriter.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBCopywriter.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2018/9/13. | ||
| 6 | -// Copyright © 2018年 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import <Foundation/Foundation.h> | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | -typedef NS_ENUM(NSInteger, YBIBCopywriterType) { | ||
| 14 | - /// 简体中文 | ||
| 15 | - YBIBCopywriterTypeSimplifiedChinese, | ||
| 16 | - /// 英文 | ||
| 17 | - YBIBCopywriterTypeEnglish | ||
| 18 | -}; | ||
| 19 | - | ||
| 20 | -/** | ||
| 21 | - 文案管理类 | ||
| 22 | - */ | ||
| 23 | -@interface YBIBCopywriter : NSObject | ||
| 24 | - | ||
| 25 | -/** | ||
| 26 | - 唯一有效单例 | ||
| 27 | - */ | ||
| 28 | -+ (instancetype)sharedCopywriter; | ||
| 29 | - | ||
| 30 | -/// 语言类型 | ||
| 31 | -@property (nonatomic, assign) YBIBCopywriterType type; | ||
| 32 | - | ||
| 33 | -#pragma - 以下文案可更改 | ||
| 34 | - | ||
| 35 | -@property (nonatomic, copy) NSString *videoIsInvalid; | ||
| 36 | - | ||
| 37 | -@property (nonatomic, copy) NSString *videoError; | ||
| 38 | - | ||
| 39 | -@property (nonatomic, copy) NSString *unableToSave; | ||
| 40 | - | ||
| 41 | -@property (nonatomic, copy) NSString *imageIsInvalid; | ||
| 42 | - | ||
| 43 | -@property (nonatomic, copy) NSString *downloadFailed; | ||
| 44 | - | ||
| 45 | -@property (nonatomic, copy) NSString *getPhotoAlbumAuthorizationFailed; | ||
| 46 | - | ||
| 47 | -@property (nonatomic, copy) NSString *saveToPhotoAlbumSuccess; | ||
| 48 | - | ||
| 49 | -@property (nonatomic, copy) NSString *saveToPhotoAlbumFailed; | ||
| 50 | - | ||
| 51 | -@property (nonatomic, copy) NSString *saveToPhotoAlbum; | ||
| 52 | - | ||
| 53 | -@property (nonatomic, copy) NSString *cancel; | ||
| 54 | - | ||
| 55 | -@end | ||
| 56 | - | ||
| 57 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Helper/YBIBCopywriter.m deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBCopywriter.m | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2018/9/13. | ||
| 6 | -// Copyright © 2018年 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBCopywriter.h" | ||
| 10 | - | ||
| 11 | -@implementation YBIBCopywriter | ||
| 12 | - | ||
| 13 | -#pragma mark - life cycle | ||
| 14 | - | ||
| 15 | -+ (instancetype)sharedCopywriter { | ||
| 16 | - static YBIBCopywriter *copywriter = nil; | ||
| 17 | - static dispatch_once_t onceToken; | ||
| 18 | - dispatch_once(&onceToken, ^{ | ||
| 19 | - copywriter = [YBIBCopywriter new]; | ||
| 20 | - }); | ||
| 21 | - return copywriter; | ||
| 22 | -} | ||
| 23 | - | ||
| 24 | -- (instancetype)init { | ||
| 25 | - self = [super init]; | ||
| 26 | - if (self) { | ||
| 27 | - _type = YBIBCopywriterTypeSimplifiedChinese; | ||
| 28 | - NSArray *appleLanguages = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"]; | ||
| 29 | - if (appleLanguages && appleLanguages.count > 0) { | ||
| 30 | - NSString *languages = appleLanguages[0]; | ||
| 31 | - if (![languages hasPrefix:@"zh-Hans"]) { | ||
| 32 | - _type = YBIBCopywriterTypeEnglish; | ||
| 33 | - } | ||
| 34 | - } | ||
| 35 | - | ||
| 36 | - [self initCopy]; | ||
| 37 | - } | ||
| 38 | - return self; | ||
| 39 | -} | ||
| 40 | - | ||
| 41 | -#pragma mark - private | ||
| 42 | - | ||
| 43 | -- (void)initCopy { | ||
| 44 | - BOOL en = self.type == YBIBCopywriterTypeEnglish; | ||
| 45 | - | ||
| 46 | - self.videoIsInvalid = en ? @"Video is invalid" : @"视频无效"; | ||
| 47 | - self.videoError = en ? @"Video error" : @"视频错误"; | ||
| 48 | - self.unableToSave = en ? @"Unable to save" : @"无法保存"; | ||
| 49 | - self.imageIsInvalid = en ? @"Image is invalid" : @"图片无效"; | ||
| 50 | - self.downloadFailed = en ? @"Download failed" : @"加载图片失败"; | ||
| 51 | - self.getPhotoAlbumAuthorizationFailed = en ? @"Failed to get album authorization" : @"获取相册权限失败"; | ||
| 52 | - self.saveToPhotoAlbumSuccess = en ? @"Save successful" : @"已保存到系统相册"; | ||
| 53 | - self.saveToPhotoAlbumFailed = en ? @"Save failed" : @"保存失败"; | ||
| 54 | - self.saveToPhotoAlbum = en ? @"Save" : @"保存到相册"; | ||
| 55 | - self.cancel = en ? @"Cancel" : @"取消"; | ||
| 56 | -} | ||
| 57 | - | ||
| 58 | -#pragma mark - public | ||
| 59 | - | ||
| 60 | -- (void)setType:(YBIBCopywriterType)type { | ||
| 61 | - _type = type; | ||
| 62 | - [self initCopy]; | ||
| 63 | -} | ||
| 64 | - | ||
| 65 | -@end |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Helper/YBIBIconManager.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBIconManager.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2018/8/29. | ||
| 6 | -// Copyright © 2018年 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import <UIKit/UIKit.h> | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | -@interface UIImage (YBImageBrowser) | ||
| 14 | - | ||
| 15 | -/** | ||
| 16 | - 获取图片便利构造方法 | ||
| 17 | - | ||
| 18 | - @param name 图片名字 | ||
| 19 | - @param bundle 资源对象 | ||
| 20 | - @return 图片实例 | ||
| 21 | - */ | ||
| 22 | -+ (instancetype)ybib_imageNamed:(NSString *)name bundle:(NSBundle *)bundle; | ||
| 23 | - | ||
| 24 | -@end | ||
| 25 | - | ||
| 26 | - | ||
| 27 | -/// 获取图片闭包 | ||
| 28 | -typedef UIImage * _Nullable (^YBIBIconBlock)(void); | ||
| 29 | - | ||
| 30 | -/** | ||
| 31 | - 图标管理类 | ||
| 32 | - */ | ||
| 33 | -@interface YBIBIconManager : NSObject | ||
| 34 | - | ||
| 35 | -/** | ||
| 36 | - 唯一有效单例 | ||
| 37 | - */ | ||
| 38 | -+ (instancetype)sharedManager; | ||
| 39 | - | ||
| 40 | -#pragma - 以下图片可更改 | ||
| 41 | - | ||
| 42 | -/// 基本-加载 | ||
| 43 | -@property (nonatomic, copy) YBIBIconBlock loadingImage; | ||
| 44 | - | ||
| 45 | -/// 工具视图-保存 | ||
| 46 | -@property (nonatomic, copy) YBIBIconBlock toolSaveImage; | ||
| 47 | -/// 工具视图-更多 | ||
| 48 | -@property (nonatomic, copy) YBIBIconBlock toolMoreImage; | ||
| 49 | - | ||
| 50 | -/// 视频-播放 | ||
| 51 | -@property (nonatomic, copy) YBIBIconBlock videoPlayImage; | ||
| 52 | -/// 视频-暂停 | ||
| 53 | -@property (nonatomic, copy) YBIBIconBlock videoPauseImage; | ||
| 54 | -/// 视频-取消 | ||
| 55 | -@property (nonatomic, copy) YBIBIconBlock videoCancelImage; | ||
| 56 | -/// 视频-播放大图 | ||
| 57 | -@property (nonatomic, copy) YBIBIconBlock videoBigPlayImage; | ||
| 58 | -/// 视频-拖动圆点 | ||
| 59 | -@property (nonatomic, copy) YBIBIconBlock videoDragCircleImage; | ||
| 60 | - | ||
| 61 | -@end | ||
| 62 | - | ||
| 63 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Helper/YBIBIconManager.m deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBIconManager.m | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2018/8/29. | ||
| 6 | -// Copyright © 2018年 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBIconManager.h" | ||
| 10 | - | ||
| 11 | -// The best order for path scale search. | ||
| 12 | -static NSArray *_NSBundlePreferredScales() { | ||
| 13 | - static NSArray *scales; | ||
| 14 | - static dispatch_once_t onceToken; | ||
| 15 | - dispatch_once(&onceToken, ^{ | ||
| 16 | - CGFloat screenScale = [UIScreen mainScreen].scale; | ||
| 17 | - if (screenScale <= 1) { | ||
| 18 | - scales = @[@1,@2,@3]; | ||
| 19 | - } else if (screenScale <= 2) { | ||
| 20 | - scales = @[@2,@3,@1]; | ||
| 21 | - } else { | ||
| 22 | - scales = @[@3,@2,@1]; | ||
| 23 | - } | ||
| 24 | - }); | ||
| 25 | - return scales; | ||
| 26 | -} | ||
| 27 | - | ||
| 28 | -// Add scale modifier to the file name (without path extension), from @"name" to @"name@2x". | ||
| 29 | -static NSString *_NSStringByAppendingNameScale(NSString *string, CGFloat scale) { | ||
| 30 | - if (!string) return nil; | ||
| 31 | - if (fabs(scale - 1) <= __FLT_EPSILON__ || string.length == 0 || [string hasSuffix:@"/"]) return string.copy; | ||
| 32 | - return [string stringByAppendingFormat:@"@%@x", @(scale)]; | ||
| 33 | -} | ||
| 34 | - | ||
| 35 | -@implementation UIImage (YBImageBrowser) | ||
| 36 | - | ||
| 37 | -+ (instancetype)ybib_imageNamed:(NSString *)name bundle:(NSBundle *)bundle { | ||
| 38 | - if (name.length == 0) return nil; | ||
| 39 | - if ([name hasSuffix:@"/"]) return nil; | ||
| 40 | - | ||
| 41 | - NSString *res = name.stringByDeletingPathExtension; | ||
| 42 | - NSString *ext = name.pathExtension; | ||
| 43 | - NSString *path = nil; | ||
| 44 | - CGFloat scale = 1; | ||
| 45 | - | ||
| 46 | - // If no extension, guess by system supported (same as UIImage). | ||
| 47 | - NSArray *exts = ext.length > 0 ? @[ext] : @[@"", @"png", @"jpeg", @"jpg", @"gif", @"webp", @"apng"]; | ||
| 48 | - NSArray *scales = _NSBundlePreferredScales(); | ||
| 49 | - for (int s = 0; s < scales.count; s++) { | ||
| 50 | - scale = ((NSNumber *)scales[s]).floatValue; | ||
| 51 | - NSString *scaledName = _NSStringByAppendingNameScale(res, scale); | ||
| 52 | - for (NSString *e in exts) { | ||
| 53 | - path = [bundle pathForResource:scaledName ofType:e]; | ||
| 54 | - if (path) break; | ||
| 55 | - } | ||
| 56 | - if (path) break; | ||
| 57 | - } | ||
| 58 | - if (path.length == 0) { | ||
| 59 | - // Assets.xcassets supported. | ||
| 60 | - return [self imageNamed:name]; | ||
| 61 | - } | ||
| 62 | - | ||
| 63 | - NSData *data = [NSData dataWithContentsOfFile:path]; | ||
| 64 | - if (data.length == 0) return nil; | ||
| 65 | - | ||
| 66 | - return [[self alloc] initWithData:data scale:scale]; | ||
| 67 | -} | ||
| 68 | - | ||
| 69 | -@end | ||
| 70 | - | ||
| 71 | - | ||
| 72 | -NSBundle *YBIBDefaultBundle(void) { | ||
| 73 | - static NSBundle *bundle = nil; | ||
| 74 | - static dispatch_once_t onceToken; | ||
| 75 | - dispatch_once(&onceToken, ^{ | ||
| 76 | - NSBundle *_bundle = [NSBundle bundleForClass:NSClassFromString(@"YBImageBrowser")]; | ||
| 77 | - NSString *path = [_bundle pathForResource:@"YBImageBrowser" ofType:@"bundle"]; | ||
| 78 | - bundle = [NSBundle bundleWithPath:path]; | ||
| 79 | - }); | ||
| 80 | - return bundle; | ||
| 81 | -} | ||
| 82 | - | ||
| 83 | -NSBundle *YBIBVideoBundle(void) { | ||
| 84 | - static NSBundle *bundle = nil; | ||
| 85 | - static dispatch_once_t onceToken; | ||
| 86 | - dispatch_once(&onceToken, ^{ | ||
| 87 | - NSBundle *_bundle = [NSBundle bundleForClass:NSClassFromString(@"YBImageBrowser")]; | ||
| 88 | - NSString *path = [_bundle pathForResource:@"YBImageBrowserVideo" ofType:@"bundle"]; | ||
| 89 | - bundle = [NSBundle bundleWithPath:path]; | ||
| 90 | - }); | ||
| 91 | - return bundle; | ||
| 92 | -} | ||
| 93 | - | ||
| 94 | -@implementation YBIBIconManager | ||
| 95 | - | ||
| 96 | -+ (instancetype)sharedManager { | ||
| 97 | - static YBIBIconManager *manager = nil; | ||
| 98 | - static dispatch_once_t onceToken; | ||
| 99 | - dispatch_once(&onceToken, ^{ | ||
| 100 | - manager = [YBIBIconManager new]; | ||
| 101 | - }); | ||
| 102 | - return manager; | ||
| 103 | -} | ||
| 104 | - | ||
| 105 | -- (instancetype)init { | ||
| 106 | - self = [super init]; | ||
| 107 | - if (self) { | ||
| 108 | - _loadingImage = ^UIImage * _Nullable{ | ||
| 109 | - return [UIImage ybib_imageNamed:@"ybib_loading" bundle:YBIBDefaultBundle()]; | ||
| 110 | - }; | ||
| 111 | - | ||
| 112 | - _toolSaveImage = ^UIImage * _Nullable{ | ||
| 113 | - return [UIImage ybib_imageNamed:@"ybib_save" bundle:YBIBDefaultBundle()]; | ||
| 114 | - }; | ||
| 115 | - _toolMoreImage = ^UIImage * _Nullable{ | ||
| 116 | - return [UIImage ybib_imageNamed:@"ybib_more" bundle:YBIBDefaultBundle()]; | ||
| 117 | - }; | ||
| 118 | - | ||
| 119 | - _videoPlayImage = ^UIImage * _Nullable{ | ||
| 120 | - return [UIImage ybib_imageNamed:@"ybib_play" bundle:YBIBVideoBundle()]; | ||
| 121 | - }; | ||
| 122 | - _videoPauseImage = ^UIImage * _Nullable{ | ||
| 123 | - return [UIImage ybib_imageNamed:@"ybib_pause" bundle:YBIBVideoBundle()]; | ||
| 124 | - }; | ||
| 125 | - _videoCancelImage = ^UIImage * _Nullable{ | ||
| 126 | - return [UIImage ybib_imageNamed:@"ybib_cancel" bundle:YBIBVideoBundle()]; | ||
| 127 | - }; | ||
| 128 | - _videoBigPlayImage = ^UIImage * _Nullable{ | ||
| 129 | - return [UIImage ybib_imageNamed:@"ybib_bigPlay" bundle:YBIBVideoBundle()]; | ||
| 130 | - }; | ||
| 131 | - _videoDragCircleImage = ^UIImage * _Nullable{ | ||
| 132 | - return [UIImage ybib_imageNamed:@"ybib_circlePoint" bundle:YBIBVideoBundle()]; | ||
| 133 | - }; | ||
| 134 | - } | ||
| 135 | - return self; | ||
| 136 | -} | ||
| 137 | - | ||
| 138 | -@end |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Helper/YBIBPhotoAlbumManager.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBPhotoAlbumManager.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2018/8/28. | ||
| 6 | -// Copyright © 2018年 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import <Photos/Photos.h> | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | -@interface YBIBPhotoAlbumManager : NSObject | ||
| 14 | - | ||
| 15 | -/** | ||
| 16 | - Get photo album authorization. | ||
| 17 | - */ | ||
| 18 | -+ (void)getPhotoAlbumAuthorizationSuccess:(void(^)(void))success failed:(void(^)(void))failed; | ||
| 19 | - | ||
| 20 | -/** | ||
| 21 | - Get 'AVAsset' by 'PHAsset' asynchronously, callback is in child thread. | ||
| 22 | - */ | ||
| 23 | -+ (void)getAVAssetWithPHAsset:(PHAsset *)phAsset completion:(void(^)(AVAsset * _Nullable asset))completion; | ||
| 24 | - | ||
| 25 | -/** | ||
| 26 | - Get 'ImageData' by 'PHAsset' synchronously, callback is in child thread. | ||
| 27 | - */ | ||
| 28 | -+ (void)getImageDataWithPHAsset:(PHAsset *)phAsset completion:(void(^)(NSData * _Nullable data))completion; | ||
| 29 | - | ||
| 30 | -@end | ||
| 31 | - | ||
| 32 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Helper/YBIBPhotoAlbumManager.m deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBPhotoAlbumManager.m | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2018/8/28. | ||
| 6 | -// Copyright © 2018年 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBPhotoAlbumManager.h" | ||
| 10 | -#import "YBIBUtilities.h" | ||
| 11 | - | ||
| 12 | -@implementation YBIBPhotoAlbumManager | ||
| 13 | - | ||
| 14 | -+ (void)getAVAssetWithPHAsset:(PHAsset *)phAsset completion:(nonnull void (^)(AVAsset * _Nullable))completion { | ||
| 15 | - PHVideoRequestOptions *options = [PHVideoRequestOptions new]; | ||
| 16 | - options.networkAccessAllowed = YES; | ||
| 17 | - [[PHImageManager defaultManager] requestAVAssetForVideo:phAsset options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) { | ||
| 18 | - completion(asset); | ||
| 19 | - }]; | ||
| 20 | -} | ||
| 21 | - | ||
| 22 | -+ (void)getImageDataWithPHAsset:(PHAsset *)phAsset completion:(nonnull void (^)(NSData * _Nullable))completion { | ||
| 23 | - PHImageRequestOptions *options = [PHImageRequestOptions new]; | ||
| 24 | - options.networkAccessAllowed = YES; | ||
| 25 | - options.resizeMode = PHImageRequestOptionsResizeModeNone; | ||
| 26 | - // Only when this property is YES, the callback will in child thread. | ||
| 27 | - options.synchronous = YES; | ||
| 28 | - [[PHImageManager defaultManager] requestImageDataForAsset:phAsset options:options resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) { | ||
| 29 | - BOOL complete = ![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey] && ![[info objectForKey:PHImageResultIsDegradedKey] boolValue]; | ||
| 30 | - if (complete && imageData) { | ||
| 31 | - completion(imageData); | ||
| 32 | - } else { | ||
| 33 | - completion(nil); | ||
| 34 | - } | ||
| 35 | - }]; | ||
| 36 | -} | ||
| 37 | - | ||
| 38 | -+ (void)getPhotoAlbumAuthorizationSuccess:(void(^)(void))success failed:(void(^)(void))failed { | ||
| 39 | - PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus]; | ||
| 40 | - switch (status) { | ||
| 41 | - case PHAuthorizationStatusDenied: | ||
| 42 | - if (failed) failed(); | ||
| 43 | - break; | ||
| 44 | - case PHAuthorizationStatusRestricted: | ||
| 45 | - if (failed) failed(); | ||
| 46 | - break; | ||
| 47 | - case PHAuthorizationStatusNotDetermined: { | ||
| 48 | - [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status){ | ||
| 49 | - YBIB_DISPATCH_ASYNC_MAIN(^{ | ||
| 50 | - if (status == PHAuthorizationStatusAuthorized) { | ||
| 51 | - if (success) success(); | ||
| 52 | - } else { | ||
| 53 | - if (failed) failed(); | ||
| 54 | - } | ||
| 55 | - }) | ||
| 56 | - }]; | ||
| 57 | - } | ||
| 58 | - break; | ||
| 59 | - case PHAuthorizationStatusAuthorized: | ||
| 60 | - if (success) success(); | ||
| 61 | - break; | ||
| 62 | - } | ||
| 63 | -} | ||
| 64 | - | ||
| 65 | -@end |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Helper/YBIBSentinel.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBSentinel.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/18. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import <Foundation/Foundation.h> | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | -/** | ||
| 14 | - Thread safe. | ||
| 15 | - */ | ||
| 16 | -@interface YBIBSentinel : NSObject | ||
| 17 | - | ||
| 18 | -/// Returns the current value of the counter. | ||
| 19 | -@property (readonly) int32_t value; | ||
| 20 | - | ||
| 21 | -/** | ||
| 22 | - Increase the value atomically. | ||
| 23 | - @return The new value. | ||
| 24 | - */ | ||
| 25 | -- (int32_t)increase; | ||
| 26 | - | ||
| 27 | -@end | ||
| 28 | - | ||
| 29 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Helper/YBIBSentinel.m deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBSentinel.m | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/18. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBSentinel.h" | ||
| 10 | -#import <libkern/OSAtomic.h> | ||
| 11 | - | ||
| 12 | -@implementation YBIBSentinel { | ||
| 13 | - int32_t _value; | ||
| 14 | -} | ||
| 15 | - | ||
| 16 | -- (int32_t)value { | ||
| 17 | - return _value; | ||
| 18 | -} | ||
| 19 | - | ||
| 20 | -- (int32_t)increase { | ||
| 21 | - return OSAtomicIncrement32(&_value); | ||
| 22 | -} | ||
| 23 | - | ||
| 24 | -@end |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Helper/YBIBUtilities.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBUtilities.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 杨少 on 2018/4/11. | ||
| 6 | -// Copyright © 2018年 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import <UIKit/UIKit.h> | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | - | ||
| 14 | -#define YBIB_DISPATCH_ASYNC(queue, block)\ | ||
| 15 | -if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(queue)) == 0) {\ | ||
| 16 | -block();\ | ||
| 17 | -} else {\ | ||
| 18 | -dispatch_async(queue, block);\ | ||
| 19 | -} | ||
| 20 | - | ||
| 21 | -#define YBIB_DISPATCH_ASYNC_MAIN(block) YBIB_DISPATCH_ASYNC(dispatch_get_main_queue(), block) | ||
| 22 | - | ||
| 23 | - | ||
| 24 | -#define YBIB_CODE_EXEC_TIME(KEY, ...) \ | ||
| 25 | -CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); \ | ||
| 26 | -__VA_ARGS__ \ | ||
| 27 | -CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime); \ | ||
| 28 | -NSLog(@"%@ Time-Consuming: %fms", KEY, linkTime * 1000.0); | ||
| 29 | - | ||
| 30 | - | ||
| 31 | -UIWindow * _Nonnull YBIBNormalWindow(void); | ||
| 32 | - | ||
| 33 | -UIViewController * _Nullable YBIBTopController(void); | ||
| 34 | -UIViewController * _Nullable YBIBTopControllerByWindow(UIWindow *); | ||
| 35 | - | ||
| 36 | -BOOL YBIBLowMemory(void); | ||
| 37 | - | ||
| 38 | -BOOL YBIBIsIphoneXSeries(void); | ||
| 39 | -CGFloat YBIBStatusbarHeight(void); | ||
| 40 | -CGFloat YBIBSafeAreaBottomHeight(void); | ||
| 41 | - | ||
| 42 | -UIImage *YBIBSnapshotView(UIView *); | ||
| 43 | - | ||
| 44 | -/// This is orientation of 'YBImageBrowser' not 'UIDevice'. | ||
| 45 | -UIEdgeInsets YBIBPaddingByBrowserOrientation(UIDeviceOrientation); | ||
| 46 | - | ||
| 47 | - | ||
| 48 | -@interface YBIBUtilities : NSObject | ||
| 49 | - | ||
| 50 | -@end | ||
| 51 | - | ||
| 52 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Helper/YBIBUtilities.m deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBUtilities.m | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 杨少 on 2018/4/11. | ||
| 6 | -// Copyright © 2018年 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBUtilities.h" | ||
| 10 | -#import <sys/utsname.h> | ||
| 11 | - | ||
| 12 | - | ||
| 13 | -UIWindow * _Nullable YBIBNormalWindow(void) { | ||
| 14 | - UIWindow *window = [[UIApplication sharedApplication] keyWindow]; | ||
| 15 | - if (window.windowLevel != UIWindowLevelNormal) { | ||
| 16 | - NSArray *windows = [[UIApplication sharedApplication] windows]; | ||
| 17 | - for(UIWindow *temp in windows) { | ||
| 18 | - if (temp.windowLevel == UIWindowLevelNormal) { | ||
| 19 | - return temp; | ||
| 20 | - } | ||
| 21 | - } | ||
| 22 | - } | ||
| 23 | - return window; | ||
| 24 | -} | ||
| 25 | - | ||
| 26 | -UIViewController * _Nullable YBIBTopController(void) { | ||
| 27 | - return YBIBTopControllerByWindow(YBIBNormalWindow()); | ||
| 28 | -} | ||
| 29 | - | ||
| 30 | -UIViewController * _Nullable YBIBTopControllerByWindow(UIWindow *window) { | ||
| 31 | - if (!window) return nil; | ||
| 32 | - | ||
| 33 | - UIViewController *top = nil; | ||
| 34 | - id nextResponder; | ||
| 35 | - if (window.subviews.count > 0) { | ||
| 36 | - UIView *frontView = [window.subviews objectAtIndex:0]; | ||
| 37 | - nextResponder = frontView.nextResponder; | ||
| 38 | - } | ||
| 39 | - if (nextResponder && [nextResponder isKindOfClass:UIViewController.class]) { | ||
| 40 | - top = nextResponder; | ||
| 41 | - } else { | ||
| 42 | - top = window.rootViewController; | ||
| 43 | - } | ||
| 44 | - | ||
| 45 | - while ([top isKindOfClass:UITabBarController.class] || [top isKindOfClass:UINavigationController.class] || top.presentedViewController) { | ||
| 46 | - if ([top isKindOfClass:UITabBarController.class]) { | ||
| 47 | - top = ((UITabBarController *)top).selectedViewController; | ||
| 48 | - } else if ([top isKindOfClass:UINavigationController.class]) { | ||
| 49 | - top = ((UINavigationController *)top).topViewController; | ||
| 50 | - } else if (top.presentedViewController) { | ||
| 51 | - top = top.presentedViewController; | ||
| 52 | - } | ||
| 53 | - } | ||
| 54 | - return top; | ||
| 55 | -} | ||
| 56 | - | ||
| 57 | -BOOL YBIBLowMemory(void) { | ||
| 58 | - static BOOL lowMemory = NO; | ||
| 59 | - static dispatch_once_t onceToken; | ||
| 60 | - dispatch_once(&onceToken, ^{ | ||
| 61 | - unsigned long long physicalMemory = [[NSProcessInfo processInfo] physicalMemory]; | ||
| 62 | - lowMemory = physicalMemory > 0 && physicalMemory < 1024 * 1024 * 1500; | ||
| 63 | - }); | ||
| 64 | - return lowMemory; | ||
| 65 | -} | ||
| 66 | - | ||
| 67 | -BOOL YBIBIsIphoneXSeries(void) { | ||
| 68 | - return YBIBStatusbarHeight() > 20; | ||
| 69 | -} | ||
| 70 | - | ||
| 71 | -CGFloat YBIBStatusbarHeight(void) { | ||
| 72 | - CGFloat height = 0; | ||
| 73 | - if (@available(iOS 11.0, *)) { | ||
| 74 | - height = UIApplication.sharedApplication.delegate.window.safeAreaInsets.top; | ||
| 75 | - } | ||
| 76 | - if (height <= 0) { | ||
| 77 | - height = UIApplication.sharedApplication.statusBarFrame.size.height; | ||
| 78 | - } | ||
| 79 | - if (height <= 0) { | ||
| 80 | - height = 20; | ||
| 81 | - } | ||
| 82 | - return height; | ||
| 83 | -} | ||
| 84 | - | ||
| 85 | -CGFloat YBIBSafeAreaBottomHeight(void) { | ||
| 86 | - CGFloat bottom = 0; | ||
| 87 | - if (@available(iOS 11.0, *)) { | ||
| 88 | - bottom = UIApplication.sharedApplication.delegate.window.safeAreaInsets.bottom; | ||
| 89 | - } | ||
| 90 | - return bottom; | ||
| 91 | -} | ||
| 92 | - | ||
| 93 | -UIImage *YBIBSnapshotView(UIView *view) { | ||
| 94 | - UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, [UIScreen mainScreen].scale); | ||
| 95 | - [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:NO]; | ||
| 96 | - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); | ||
| 97 | - UIGraphicsEndImageContext(); | ||
| 98 | - return image; | ||
| 99 | -} | ||
| 100 | - | ||
| 101 | -UIEdgeInsets YBIBPaddingByBrowserOrientation(UIDeviceOrientation orientation) { | ||
| 102 | - UIEdgeInsets padding = UIEdgeInsetsZero; | ||
| 103 | - if (!YBIBIsIphoneXSeries()) return padding; | ||
| 104 | - | ||
| 105 | - UIDeviceOrientation barOrientation = (UIDeviceOrientation)UIApplication.sharedApplication.statusBarOrientation; | ||
| 106 | - | ||
| 107 | - if (UIDeviceOrientationIsLandscape(orientation)) { | ||
| 108 | - BOOL same = orientation == barOrientation; | ||
| 109 | - BOOL reverse = !same && UIDeviceOrientationIsLandscape(barOrientation); | ||
| 110 | - if (same) { | ||
| 111 | - padding.bottom = YBIBSafeAreaBottomHeight(); | ||
| 112 | - padding.top = 0; | ||
| 113 | - } else if (reverse) { | ||
| 114 | - padding.top = YBIBSafeAreaBottomHeight(); | ||
| 115 | - padding.bottom = 0; | ||
| 116 | - } | ||
| 117 | - padding.left = padding.right = MAX(YBIBSafeAreaBottomHeight(), YBIBStatusbarHeight()); | ||
| 118 | - } else { | ||
| 119 | - if (orientation == UIDeviceOrientationPortrait) { | ||
| 120 | - padding.top = YBIBStatusbarHeight(); | ||
| 121 | - padding.bottom = barOrientation == UIDeviceOrientationPortrait ? YBIBSafeAreaBottomHeight() : 0; | ||
| 122 | - } else { | ||
| 123 | - padding.bottom = YBIBStatusbarHeight(); | ||
| 124 | - padding.top = barOrientation == UIDeviceOrientationPortrait ? YBIBSafeAreaBottomHeight() : 0; | ||
| 125 | - } | ||
| 126 | - padding.left = padding.right = UIDeviceOrientationIsLandscape(barOrientation) ? YBIBSafeAreaBottomHeight() : 0 ; | ||
| 127 | - } | ||
| 128 | - return padding; | ||
| 129 | -} | ||
| 130 | - | ||
| 131 | - | ||
| 132 | -@implementation YBIBUtilities | ||
| 133 | - | ||
| 134 | -@end |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Image/YBIBImageCache+Internal.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBImageCache+Internal.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/13. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBImageCache.h" | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | -typedef NS_ENUM(NSInteger, YBIBImageCacheType) { | ||
| 14 | - YBIBImageCacheTypeOrigin, | ||
| 15 | - YBIBImageCacheTypeCompressed | ||
| 16 | -}; | ||
| 17 | - | ||
| 18 | -/** | ||
| 19 | - Not thread safe. | ||
| 20 | - */ | ||
| 21 | -@interface YBIBImageCache () | ||
| 22 | - | ||
| 23 | -- (void)setImage:(UIImage *)image type:(YBIBImageCacheType)type forKey:(NSString *)key resident:(BOOL)resident; | ||
| 24 | - | ||
| 25 | -- (nullable UIImage *)imageForKey:(NSString *)key type:(YBIBImageCacheType)type; | ||
| 26 | - | ||
| 27 | -- (void)removeForKey:(NSString *)key; | ||
| 28 | - | ||
| 29 | -- (void)removeResidentForKey:(NSString *)key; | ||
| 30 | - | ||
| 31 | -@end | ||
| 32 | - | ||
| 33 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Image/YBIBImageCache.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBImageCache.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/13. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import <UIKit/UIKit.h> | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | -@class YBIBImageCache; | ||
| 14 | - | ||
| 15 | -@interface NSObject (YBIBImageCache) | ||
| 16 | - | ||
| 17 | -/// 图片浏览器持有的图片缓存管理类 | ||
| 18 | -@property (nonatomic, strong, readonly) YBIBImageCache *ybib_imageCache; | ||
| 19 | - | ||
| 20 | -@end | ||
| 21 | - | ||
| 22 | - | ||
| 23 | -@interface YBIBImageCache : NSObject | ||
| 24 | - | ||
| 25 | -/// 缓存数量限制(一个单位表示一个 YBIBImageData 产生的所有图片数据) | ||
| 26 | -@property (nonatomic, assign) NSUInteger imageCacheCountLimit; | ||
| 27 | - | ||
| 28 | -@end | ||
| 29 | - | ||
| 30 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Image/YBIBImageCache.m deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBImageCache.m | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/13. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBImageCache.h" | ||
| 10 | -#import "YBIBImageCache+Internal.h" | ||
| 11 | -#import "YBIBUtilities.h" | ||
| 12 | -#import <objc/runtime.h> | ||
| 13 | - | ||
| 14 | - | ||
| 15 | -@implementation NSObject (YBIBImageCache) | ||
| 16 | -static void *YBIBImageCacheKey = &YBIBImageCacheKey; | ||
| 17 | -- (void)setYbib_imageCache:(YBIBImageCache *)ybib_imageCache { | ||
| 18 | - objc_setAssociatedObject(self, YBIBImageCacheKey, ybib_imageCache, OBJC_ASSOCIATION_RETAIN_NONATOMIC); | ||
| 19 | -} | ||
| 20 | -- (YBIBImageCache *)ybib_imageCache { | ||
| 21 | - YBIBImageCache *cache = objc_getAssociatedObject(self, YBIBImageCacheKey); | ||
| 22 | - if (!cache) { | ||
| 23 | - cache = [YBIBImageCache new]; | ||
| 24 | - self.ybib_imageCache = cache; | ||
| 25 | - } | ||
| 26 | - return cache; | ||
| 27 | -} | ||
| 28 | -@end | ||
| 29 | - | ||
| 30 | - | ||
| 31 | -@interface YBIBImageCachePack : NSObject | ||
| 32 | -@property (nonatomic, strong) UIImage *originImage; | ||
| 33 | -@property (nonatomic, strong) UIImage *compressedImage; | ||
| 34 | -@end | ||
| 35 | -@implementation YBIBImageCachePack | ||
| 36 | -@end | ||
| 37 | - | ||
| 38 | - | ||
| 39 | -@implementation YBIBImageCache { | ||
| 40 | - NSCache<NSString *, YBIBImageCachePack *> *_imageCache; | ||
| 41 | - NSMutableDictionary<NSString *, YBIBImageCachePack *> *_residentCache; | ||
| 42 | -} | ||
| 43 | - | ||
| 44 | -#pragma mark - life cycle | ||
| 45 | - | ||
| 46 | -- (void)dealloc { | ||
| 47 | - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; | ||
| 48 | -} | ||
| 49 | - | ||
| 50 | -- (instancetype)init { | ||
| 51 | - self = [super init]; | ||
| 52 | - if (self) { | ||
| 53 | - _imageCache = [NSCache new]; | ||
| 54 | - _imageCache.countLimit = _imageCacheCountLimit = YBIBLowMemory() ? 6 : 12; | ||
| 55 | - _residentCache = [NSMutableDictionary dictionary]; | ||
| 56 | - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMemoryWarning:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; | ||
| 57 | - } | ||
| 58 | - return self; | ||
| 59 | -} | ||
| 60 | - | ||
| 61 | -#pragma mark - event | ||
| 62 | - | ||
| 63 | -- (void)didReceiveMemoryWarning:(NSNotification *)notification { | ||
| 64 | - [_imageCache removeAllObjects]; | ||
| 65 | - [_residentCache removeAllObjects]; | ||
| 66 | -} | ||
| 67 | - | ||
| 68 | -#pragma mark - public | ||
| 69 | - | ||
| 70 | -- (void)setImage:(UIImage *)image type:(YBIBImageCacheType)type forKey:(NSString *)key resident:(BOOL)resident { | ||
| 71 | - YBIBImageCachePack *pack = [_imageCache objectForKey:key]; | ||
| 72 | - if (!pack) { | ||
| 73 | - pack = [YBIBImageCachePack new]; | ||
| 74 | - [_imageCache setObject:pack forKey:key]; | ||
| 75 | - } | ||
| 76 | - switch (type) { | ||
| 77 | - case YBIBImageCacheTypeOrigin: | ||
| 78 | - pack.originImage = image; | ||
| 79 | - break; | ||
| 80 | - case YBIBImageCacheTypeCompressed: | ||
| 81 | - pack.compressedImage = image; | ||
| 82 | - break; | ||
| 83 | - } | ||
| 84 | - [_residentCache setObject:pack forKey:key]; | ||
| 85 | -} | ||
| 86 | - | ||
| 87 | -- (UIImage *)imageForKey:(NSString *)key type:(YBIBImageCacheType)type { | ||
| 88 | - YBIBImageCachePack *pack = [_imageCache objectForKey:key] ?: [_residentCache objectForKey:key]; | ||
| 89 | - switch (type) { | ||
| 90 | - case YBIBImageCacheTypeOrigin: return pack.originImage; | ||
| 91 | - case YBIBImageCacheTypeCompressed: return pack.compressedImage; | ||
| 92 | - default: return nil; | ||
| 93 | - } | ||
| 94 | -} | ||
| 95 | - | ||
| 96 | -- (void)removeForKey:(NSString *)key { | ||
| 97 | - [_imageCache removeObjectForKey:key]; | ||
| 98 | - [_residentCache removeObjectForKey:key]; | ||
| 99 | -} | ||
| 100 | - | ||
| 101 | -- (void)removeResidentForKey:(NSString *)key { | ||
| 102 | - [_residentCache removeObjectForKey:key]; | ||
| 103 | -} | ||
| 104 | - | ||
| 105 | -#pragma mark - setter | ||
| 106 | - | ||
| 107 | -- (void)setImageCacheCountLimit:(NSUInteger)imageCacheCountLimit { | ||
| 108 | - _imageCacheCountLimit = imageCacheCountLimit; | ||
| 109 | - _imageCache.countLimit = imageCacheCountLimit; | ||
| 110 | -} | ||
| 111 | - | ||
| 112 | -@end |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Image/YBIBImageCell+Internal.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBImageCell+Internal.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/12/23. | ||
| 6 | -// Copyright © 2019 杨波. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBImageCell.h" | ||
| 10 | -#import "YBIBImageScrollView.h" | ||
| 11 | - | ||
| 12 | -NS_ASSUME_NONNULL_BEGIN | ||
| 13 | - | ||
| 14 | -@interface YBIBImageCell () | ||
| 15 | - | ||
| 16 | -@property (nonatomic, strong) YBIBImageScrollView *imageScrollView; | ||
| 17 | - | ||
| 18 | -@property (nonatomic, strong) UIImageView *tailoringImageView; | ||
| 19 | - | ||
| 20 | -@end | ||
| 21 | - | ||
| 22 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Image/YBIBImageCell.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBImageCell.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/5. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBCellProtocol.h" | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | -@interface YBIBImageCell : UICollectionViewCell <YBIBCellProtocol> | ||
| 14 | - | ||
| 15 | -@end | ||
| 16 | - | ||
| 17 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Image/YBIBImageCell.m deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBImageCell.m | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/5. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBImageCell.h" | ||
| 10 | -#import "YBIBImageData.h" | ||
| 11 | -#import "YBIBIconManager.h" | ||
| 12 | -#import "YBIBImageCell+Internal.h" | ||
| 13 | -#import "YBIBImageData+Internal.h" | ||
| 14 | -#import "YBIBCopywriter.h" | ||
| 15 | -#import "YBIBUtilities.h" | ||
| 16 | - | ||
| 17 | -@interface YBIBImageCell () <YBIBImageDataDelegate, UIScrollViewDelegate, UIGestureRecognizerDelegate> | ||
| 18 | -@end | ||
| 19 | - | ||
| 20 | -@implementation YBIBImageCell { | ||
| 21 | - CGPoint _interactStartPoint; | ||
| 22 | - BOOL _interacting; | ||
| 23 | -} | ||
| 24 | - | ||
| 25 | -#pragma mark - life cycle | ||
| 26 | - | ||
| 27 | -- (instancetype)initWithFrame:(CGRect)frame { | ||
| 28 | - self = [super initWithFrame:frame]; | ||
| 29 | - if (self) { | ||
| 30 | - [self initValue]; | ||
| 31 | - [self.contentView addSubview:self.imageScrollView]; | ||
| 32 | - [self addGesture]; | ||
| 33 | - } | ||
| 34 | - return self; | ||
| 35 | -} | ||
| 36 | - | ||
| 37 | -- (void)layoutSubviews { | ||
| 38 | - [super layoutSubviews]; | ||
| 39 | - self.imageScrollView.frame = self.bounds; | ||
| 40 | -} | ||
| 41 | - | ||
| 42 | -- (void)initValue { | ||
| 43 | - _interactStartPoint = CGPointZero; | ||
| 44 | - _interacting = NO; | ||
| 45 | -} | ||
| 46 | - | ||
| 47 | -- (void)prepareForReuse { | ||
| 48 | - ((YBIBImageData *)self.yb_cellData).delegate = nil; | ||
| 49 | - [self.imageScrollView reset]; | ||
| 50 | - [self hideTailoringImageView]; | ||
| 51 | - [self hideAuxiliaryView]; | ||
| 52 | - [super prepareForReuse]; | ||
| 53 | -} | ||
| 54 | - | ||
| 55 | -#pragma mark - <YBIBCellProtocol> | ||
| 56 | - | ||
| 57 | -@synthesize yb_currentOrientation = _yb_currentOrientation; | ||
| 58 | -@synthesize yb_containerSize = _yb_containerSize; | ||
| 59 | -@synthesize yb_backView = _yb_backView; | ||
| 60 | -@synthesize yb_collectionView = _yb_collectionView; | ||
| 61 | -@synthesize yb_isTransitioning = _yb_isTransitioning; | ||
| 62 | -@synthesize yb_isRotating = _yb_isRotating; | ||
| 63 | -@synthesize yb_auxiliaryViewHandler = _yb_auxiliaryViewHandler; | ||
| 64 | -@synthesize yb_hideStatusBar = _yb_hideStatusBar; | ||
| 65 | -@synthesize yb_hideBrowser = _yb_hideBrowser; | ||
| 66 | -@synthesize yb_hideToolViews = _yb_hideToolViews; | ||
| 67 | -@synthesize yb_cellData = _yb_cellData; | ||
| 68 | -@synthesize yb_cellIsInCenter = _yb_cellIsInCenter; | ||
| 69 | -@synthesize yb_selfPage = _yb_selfPage; | ||
| 70 | -@synthesize yb_currentPage = _yb_currentPage; | ||
| 71 | - | ||
| 72 | -- (void)setYb_cellData:(id<YBIBDataProtocol>)yb_cellData { | ||
| 73 | - _yb_cellData = yb_cellData; | ||
| 74 | - ((YBIBImageData *)yb_cellData).delegate = self; | ||
| 75 | -} | ||
| 76 | - | ||
| 77 | -- (UIView *)yb_foregroundView { | ||
| 78 | - return self.imageScrollView.imageView; | ||
| 79 | -} | ||
| 80 | - | ||
| 81 | -- (void)yb_orientationWillChangeWithExpectOrientation:(UIDeviceOrientation)orientation { | ||
| 82 | - [self hideTailoringImageView]; | ||
| 83 | -} | ||
| 84 | - | ||
| 85 | -- (void)yb_orientationChangeAnimationWithExpectOrientation:(UIDeviceOrientation)orientation { | ||
| 86 | - [self updateImageLayoutWithOrientation:orientation previousImageSize:self.imageScrollView.imageView.image.size]; | ||
| 87 | -} | ||
| 88 | - | ||
| 89 | -#pragma mark - private | ||
| 90 | - | ||
| 91 | -- (CGSize)contentSizeWithContainerSize:(CGSize)containerSize imageViewFrame:(CGRect)imageViewFrame { | ||
| 92 | - return CGSizeMake(MAX(containerSize.width, imageViewFrame.size.width), MAX(containerSize.height, imageViewFrame.size.height)); | ||
| 93 | -} | ||
| 94 | - | ||
| 95 | -- (void)updateImageLayoutWithOrientation:(UIDeviceOrientation)orientation previousImageSize:(CGSize)previousImageSize { | ||
| 96 | - if (_interacting) [self restoreInteractionWithDuration:0]; | ||
| 97 | - | ||
| 98 | - YBIBImageData *data = self.yb_cellData; | ||
| 99 | - | ||
| 100 | - CGSize imageSize; | ||
| 101 | - | ||
| 102 | - UIImage *image = self.imageScrollView.imageView.image; | ||
| 103 | - YBIBScrollImageType imageType = self.imageScrollView.imageType; | ||
| 104 | - if (imageType == YBIBScrollImageTypeCompressed) { | ||
| 105 | - imageSize = data.originImage ? data.originImage.size : image.size; | ||
| 106 | - } else { | ||
| 107 | - imageSize = image.size; | ||
| 108 | - } | ||
| 109 | - | ||
| 110 | - CGSize containerSize = self.yb_containerSize(orientation); | ||
| 111 | - CGRect imageViewFrame = [data.layout yb_imageViewFrameWithContainerSize:containerSize imageSize:imageSize orientation:orientation]; | ||
| 112 | - CGSize contentSize = [self contentSizeWithContainerSize:containerSize imageViewFrame:imageViewFrame]; | ||
| 113 | - CGFloat maxZoomScale = imageType == YBIBScrollImageTypeThumb ? 1 : [data.layout yb_maximumZoomScaleWithContainerSize:containerSize imageSize:imageSize orientation:orientation]; | ||
| 114 | - | ||
| 115 | - // 'zoomScale' must set before 'contentSize' and 'imageView.frame'. | ||
| 116 | - self.imageScrollView.zoomScale = 1; | ||
| 117 | - self.imageScrollView.contentSize = contentSize; | ||
| 118 | - self.imageScrollView.minimumZoomScale = 1; | ||
| 119 | - self.imageScrollView.maximumZoomScale = maxZoomScale; | ||
| 120 | - | ||
| 121 | - CGFloat scale; | ||
| 122 | - if (previousImageSize.width > 0 && previousImageSize.height > 0) { | ||
| 123 | - scale = imageSize.width / imageSize.height - previousImageSize.width / previousImageSize.height; | ||
| 124 | - } else { | ||
| 125 | - scale = 0; | ||
| 126 | - } | ||
| 127 | - // '0.001' is admissible error. | ||
| 128 | - if (ABS(scale) <= 0.001) { | ||
| 129 | - self.imageScrollView.imageView.frame = imageViewFrame; | ||
| 130 | - } else { | ||
| 131 | - [UIView animateWithDuration:0.25 animations:^{ | ||
| 132 | - self.imageScrollView.imageView.frame = imageViewFrame; | ||
| 133 | - }]; | ||
| 134 | - } | ||
| 135 | -} | ||
| 136 | - | ||
| 137 | -- (void)cuttingImage { | ||
| 138 | - // This method has been delayed called, so 'browser' may be in transit now. | ||
| 139 | - if (self.yb_isTransitioning()) return; | ||
| 140 | - if (_interacting) return; | ||
| 141 | - | ||
| 142 | - YBIBImageData *data = self.yb_cellData; | ||
| 143 | - if (!data.originImage) return; | ||
| 144 | - | ||
| 145 | - if (self.imageScrollView.zoomScale < data.cuttingZoomScale) return; | ||
| 146 | - | ||
| 147 | - if ([data shouldCompress]) { | ||
| 148 | - [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(cuttingImage_) object:nil]; | ||
| 149 | - [self performSelector:@selector(cuttingImage_) withObject:nil afterDelay:0.15]; | ||
| 150 | - } | ||
| 151 | -} | ||
| 152 | -- (void)cuttingImage_ { | ||
| 153 | - YBIBImageData *data = self.yb_cellData; | ||
| 154 | - if (!data.originImage) return; | ||
| 155 | - | ||
| 156 | - CGFloat scale = data.originImage.size.width / self.imageScrollView.contentSize.width; | ||
| 157 | - CGFloat x = self.imageScrollView.contentOffset.x * scale, | ||
| 158 | - y = self.imageScrollView.contentOffset.y * scale, | ||
| 159 | - width = self.imageScrollView.bounds.size.width * scale, | ||
| 160 | - height = self.imageScrollView.bounds.size.height * scale; | ||
| 161 | - | ||
| 162 | - __weak typeof(self) wSelf = self; | ||
| 163 | - [data cuttingImageToRect:CGRectMake(x, y, width, height) complete:^(UIImage *image) { | ||
| 164 | - if (!image) return; | ||
| 165 | - YBIB_DISPATCH_ASYNC_MAIN(^{ | ||
| 166 | - __strong typeof(wSelf) self = wSelf; | ||
| 167 | - if (!self) return; | ||
| 168 | - if (data == self.yb_cellData && !self.imageScrollView.isDragging && !self->_interacting && !self.yb_isTransitioning()) { | ||
| 169 | - [self showTailoringImageView:image]; | ||
| 170 | - } | ||
| 171 | - }) | ||
| 172 | - }]; | ||
| 173 | -} | ||
| 174 | - | ||
| 175 | -- (void)showTailoringImageView:(UIImage *)image { | ||
| 176 | - CGSize containerSize = self.yb_containerSize(self.yb_currentOrientation()); | ||
| 177 | - if (!self.tailoringImageView.superview) { | ||
| 178 | - [self.contentView addSubview:self.tailoringImageView]; | ||
| 179 | - } | ||
| 180 | - self.tailoringImageView.frame = CGRectMake(0, 0, containerSize.width, containerSize.height); | ||
| 181 | - self.tailoringImageView.hidden = NO; | ||
| 182 | - self.tailoringImageView.image = image; | ||
| 183 | -} | ||
| 184 | - | ||
| 185 | -- (void)hideTailoringImageView { | ||
| 186 | - // Don't use 'getter' method, because it's according to the need to load. | ||
| 187 | - if (_tailoringImageView) { | ||
| 188 | - self.tailoringImageView.hidden = YES; | ||
| 189 | - } | ||
| 190 | -} | ||
| 191 | - | ||
| 192 | -- (void)hideAuxiliaryView { | ||
| 193 | - [self.yb_auxiliaryViewHandler() yb_hideLoadingWithContainer:self]; | ||
| 194 | - [self.yb_auxiliaryViewHandler() yb_hideToastWithContainer:self]; | ||
| 195 | -} | ||
| 196 | - | ||
| 197 | -- (void)hideBrowser { | ||
| 198 | - ((YBIBImageData *)self.yb_cellData).delegate = nil; | ||
| 199 | - [self hideTailoringImageView]; | ||
| 200 | - [self hideAuxiliaryView]; | ||
| 201 | - self.yb_hideBrowser(); | ||
| 202 | - _interacting = NO; | ||
| 203 | -} | ||
| 204 | - | ||
| 205 | -#pragma mark - <YBIBImageDataDelegate> | ||
| 206 | - | ||
| 207 | -- (void)yb_imageData:(YBIBImageData *)data startLoadingWithStatus:(YBIBImageLoadingStatus)status { | ||
| 208 | - switch (status) { | ||
| 209 | - case YBIBImageLoadingStatusDecoding: { | ||
| 210 | - if (!self.imageScrollView.imageView.image) { | ||
| 211 | - [self.yb_auxiliaryViewHandler() yb_showLoadingWithContainer:self]; | ||
| 212 | - } | ||
| 213 | - } | ||
| 214 | - break; | ||
| 215 | - case YBIBImageLoadingStatusProcessing: { | ||
| 216 | - if (!self.imageScrollView.imageView.image) { | ||
| 217 | - [self.yb_auxiliaryViewHandler() yb_showLoadingWithContainer:self]; | ||
| 218 | - } | ||
| 219 | - } | ||
| 220 | - break; | ||
| 221 | - case YBIBImageLoadingStatusCompressing: { | ||
| 222 | - if (!self.imageScrollView.imageView.image) { | ||
| 223 | - [self.yb_auxiliaryViewHandler() yb_showLoadingWithContainer:self]; | ||
| 224 | - } | ||
| 225 | - } | ||
| 226 | - break; | ||
| 227 | - case YBIBImageLoadingStatusReadingPHAsset: { | ||
| 228 | - if (!self.imageScrollView.imageView.image) { | ||
| 229 | - [self.yb_auxiliaryViewHandler() yb_showLoadingWithContainer:self]; | ||
| 230 | - } | ||
| 231 | - } | ||
| 232 | - break; | ||
| 233 | - case YBIBImageLoadingStatusNone: { | ||
| 234 | - [self hideAuxiliaryView]; | ||
| 235 | - } | ||
| 236 | - break; | ||
| 237 | - default: | ||
| 238 | - break; | ||
| 239 | - } | ||
| 240 | -} | ||
| 241 | - | ||
| 242 | -- (void)yb_imageData:(YBIBImageData *)data readyForImage:(__kindof UIImage *)image { | ||
| 243 | - [self.yb_auxiliaryViewHandler() yb_hideLoadingWithContainer:self]; | ||
| 244 | - if (self.imageScrollView.imageView.image == image) return; | ||
| 245 | - | ||
| 246 | - CGSize size = self.imageScrollView.imageView.image.size; | ||
| 247 | - [self.imageScrollView setImage:image type:YBIBScrollImageTypeOriginal]; | ||
| 248 | - [self updateImageLayoutWithOrientation:self.yb_currentOrientation() previousImageSize:size]; | ||
| 249 | -} | ||
| 250 | - | ||
| 251 | -- (void)yb_imageData:(YBIBImageData *)data readyForCompressedImage:(__kindof UIImage *)image { | ||
| 252 | - [self.yb_auxiliaryViewHandler() yb_hideLoadingWithContainer:self]; | ||
| 253 | - if (self.imageScrollView.imageView.image == image) return; | ||
| 254 | - | ||
| 255 | - CGSize size = self.imageScrollView.imageView.image.size; | ||
| 256 | - [self.imageScrollView setImage:image type:YBIBScrollImageTypeCompressed]; | ||
| 257 | - [self updateImageLayoutWithOrientation:self.yb_currentOrientation() previousImageSize:size]; | ||
| 258 | -} | ||
| 259 | - | ||
| 260 | -- (void)yb_imageData:(YBIBImageData *)data readyForThumbImage:(__kindof UIImage *)image { | ||
| 261 | - if (self.imageScrollView.imageView.image) return; | ||
| 262 | - | ||
| 263 | - [self.imageScrollView setImage:image type:YBIBScrollImageTypeThumb]; | ||
| 264 | - [self updateImageLayoutWithOrientation:self.yb_currentOrientation() previousImageSize:image.size]; | ||
| 265 | -} | ||
| 266 | - | ||
| 267 | -- (void)yb_imageIsInvalidForData:(YBIBImageData *)data { | ||
| 268 | - [self.yb_auxiliaryViewHandler() yb_hideLoadingWithContainer:self]; | ||
| 269 | - NSString *imageIsInvalid = [YBIBCopywriter sharedCopywriter].imageIsInvalid; | ||
| 270 | - if (self.imageScrollView.imageView.image) { | ||
| 271 | - [self.yb_auxiliaryViewHandler() yb_showIncorrectToastWithContainer:self text:imageIsInvalid]; | ||
| 272 | - } else { | ||
| 273 | - [self.yb_auxiliaryViewHandler() yb_showLoadingWithContainer:self text:imageIsInvalid]; | ||
| 274 | - } | ||
| 275 | -} | ||
| 276 | - | ||
| 277 | -- (void)yb_imageData:(YBIBImageData *)data downloadProgress:(CGFloat)progress { | ||
| 278 | - [self.yb_auxiliaryViewHandler() yb_showLoadingWithContainer:self progress:progress]; | ||
| 279 | -} | ||
| 280 | - | ||
| 281 | -- (void)yb_imageDownloadFailedForData:(YBIBImageData *)data { | ||
| 282 | - if (self.imageScrollView.imageView.image) { | ||
| 283 | - [self.yb_auxiliaryViewHandler() yb_hideLoadingWithContainer:self]; | ||
| 284 | - [self.yb_auxiliaryViewHandler() yb_showIncorrectToastWithContainer:self text:[YBIBCopywriter sharedCopywriter].downloadFailed]; | ||
| 285 | - } else { | ||
| 286 | - [self.yb_auxiliaryViewHandler() yb_showLoadingWithContainer:self text:[YBIBCopywriter sharedCopywriter].downloadFailed]; | ||
| 287 | - } | ||
| 288 | -} | ||
| 289 | - | ||
| 290 | -#pragma mark - gesture | ||
| 291 | - | ||
| 292 | -- (void)addGesture { | ||
| 293 | - UITapGestureRecognizer *tapSingle = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(respondsToTapSingle:)]; | ||
| 294 | - tapSingle.numberOfTapsRequired = 1; | ||
| 295 | - UITapGestureRecognizer *tapDouble = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(respondsToTapDouble:)]; | ||
| 296 | - tapDouble.numberOfTapsRequired = 2; | ||
| 297 | - UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(respondsToPan:)]; | ||
| 298 | - pan.maximumNumberOfTouches = 1; | ||
| 299 | - pan.delegate = self; | ||
| 300 | - | ||
| 301 | - [tapSingle requireGestureRecognizerToFail:tapDouble]; | ||
| 302 | - [tapSingle requireGestureRecognizerToFail:pan]; | ||
| 303 | - [tapDouble requireGestureRecognizerToFail:pan]; | ||
| 304 | - | ||
| 305 | - [self addGestureRecognizer:tapSingle]; | ||
| 306 | - [self addGestureRecognizer:tapDouble]; | ||
| 307 | - [self addGestureRecognizer:pan]; | ||
| 308 | -} | ||
| 309 | - | ||
| 310 | -- (void)respondsToTapSingle:(UITapGestureRecognizer *)tap { | ||
| 311 | - if (self.yb_isRotating()) return; | ||
| 312 | - | ||
| 313 | - YBIBImageData *data = self.yb_cellData; | ||
| 314 | - if (data.singleTouchBlock) { | ||
| 315 | - data.singleTouchBlock(data); | ||
| 316 | - } else { | ||
| 317 | - [self hideTailoringImageView]; | ||
| 318 | - [self hideAuxiliaryView]; | ||
| 319 | - self.yb_hideBrowser(); | ||
| 320 | - } | ||
| 321 | -} | ||
| 322 | - | ||
| 323 | -- (void)respondsToTapDouble:(UITapGestureRecognizer *)tap { | ||
| 324 | - if (self.yb_isRotating()) return; | ||
| 325 | - | ||
| 326 | - [self hideTailoringImageView]; | ||
| 327 | - | ||
| 328 | - UIScrollView *scrollView = self.imageScrollView; | ||
| 329 | - UIView *zoomView = [self viewForZoomingInScrollView:scrollView]; | ||
| 330 | - CGPoint point = [tap locationInView:zoomView]; | ||
| 331 | - if (!CGRectContainsPoint(zoomView.bounds, point)) return; | ||
| 332 | - if (scrollView.zoomScale == scrollView.maximumZoomScale) { | ||
| 333 | - [scrollView setZoomScale:1 animated:YES]; | ||
| 334 | - } else { | ||
| 335 | - [scrollView zoomToRect:CGRectMake(point.x, point.y, 1, 1) animated:YES]; | ||
| 336 | - } | ||
| 337 | -} | ||
| 338 | - | ||
| 339 | -- (void)respondsToPan:(UIPanGestureRecognizer *)pan { | ||
| 340 | - if (self.yb_isRotating()) return; | ||
| 341 | - | ||
| 342 | - YBIBInteractionProfile *profile = ((YBIBImageData *)self.yb_cellData).interactionProfile; | ||
| 343 | - if (profile.disable) return; | ||
| 344 | - if ((CGRectIsEmpty(self.imageScrollView.imageView.frame) || !self.imageScrollView.imageView.image)) return; | ||
| 345 | - | ||
| 346 | - CGPoint point = [pan locationInView:self]; | ||
| 347 | - CGSize containerSize = self.yb_containerSize(self.yb_currentOrientation()); | ||
| 348 | - | ||
| 349 | - if (pan.state == UIGestureRecognizerStateBegan) { | ||
| 350 | - _interactStartPoint = point; | ||
| 351 | - } else if (pan.state == UIGestureRecognizerStateCancelled || pan.state == UIGestureRecognizerStateEnded || pan.state == UIGestureRecognizerStateRecognized || pan.state == UIGestureRecognizerStateFailed) { | ||
| 352 | - | ||
| 353 | - // End. | ||
| 354 | - if (_interacting) { | ||
| 355 | - CGPoint velocity = [pan velocityInView:self.imageScrollView]; | ||
| 356 | - | ||
| 357 | - BOOL velocityArrive = ABS(velocity.y) > profile.dismissVelocityY; | ||
| 358 | - BOOL distanceArrive = ABS(point.y - _interactStartPoint.y) > containerSize.height * profile.dismissScale; | ||
| 359 | - | ||
| 360 | - BOOL shouldDismiss = distanceArrive || velocityArrive; | ||
| 361 | - if (shouldDismiss) { | ||
| 362 | - [self hideBrowser]; | ||
| 363 | - } else { | ||
| 364 | - [self restoreInteractionWithDuration:profile.restoreDuration]; | ||
| 365 | - } | ||
| 366 | - } | ||
| 367 | - | ||
| 368 | - } else if (pan.state == UIGestureRecognizerStateChanged) { | ||
| 369 | - if (_interacting) { | ||
| 370 | - | ||
| 371 | - // Change. | ||
| 372 | - self.imageScrollView.center = point; | ||
| 373 | - CGFloat scale = 1 - ABS(point.y - _interactStartPoint.y) / (containerSize.height * 1.2); | ||
| 374 | - if (scale > 1) scale = 1; | ||
| 375 | - if (scale < 0.35) scale = 0.35; | ||
| 376 | - self.imageScrollView.transform = CGAffineTransformMakeScale(scale, scale); | ||
| 377 | - | ||
| 378 | - CGFloat alpha = 1 - ABS(point.y - _interactStartPoint.y) / (containerSize.height * 0.7); | ||
| 379 | - if (alpha > 1) alpha = 1; | ||
| 380 | - if (alpha < 0) alpha = 0; | ||
| 381 | - self.yb_backView.backgroundColor = [self.yb_backView.backgroundColor colorWithAlphaComponent:alpha]; | ||
| 382 | - | ||
| 383 | - } else { | ||
| 384 | - | ||
| 385 | - // Start. | ||
| 386 | - if (CGPointEqualToPoint(_interactStartPoint, CGPointZero) || self.yb_currentPage() != self.yb_selfPage() || !self.yb_cellIsInCenter() || self.imageScrollView.isZooming) return; | ||
| 387 | - | ||
| 388 | - CGPoint velocity = [pan velocityInView:self.imageScrollView]; | ||
| 389 | - CGFloat triggerDistance = profile.triggerDistance; | ||
| 390 | - CGFloat offsetY = self.imageScrollView.contentOffset.y, height = self.imageScrollView.bounds.size.height; | ||
| 391 | - | ||
| 392 | - BOOL distanceArrive = ABS(point.x - _interactStartPoint.x) < triggerDistance && ABS(velocity.x) < 500; | ||
| 393 | - BOOL upArrive = point.y - _interactStartPoint.y > triggerDistance && offsetY <= 1; | ||
| 394 | - BOOL downArrive = point.y - _interactStartPoint.y < -triggerDistance && offsetY + height >= MAX(self.imageScrollView.contentSize.height, height) - 1; | ||
| 395 | - | ||
| 396 | - BOOL shouldStart = (upArrive || downArrive) && distanceArrive; | ||
| 397 | - if (!shouldStart) return; | ||
| 398 | - | ||
| 399 | - _interactStartPoint = point; | ||
| 400 | - | ||
| 401 | - CGRect startFrame = self.imageScrollView.frame; | ||
| 402 | - CGFloat anchorX = point.x / startFrame.size.width, anchorY = point.y / startFrame.size.height; | ||
| 403 | - self.imageScrollView.layer.anchorPoint = CGPointMake(anchorX, anchorY); | ||
| 404 | - self.imageScrollView.userInteractionEnabled = NO; | ||
| 405 | - self.imageScrollView.scrollEnabled = NO; | ||
| 406 | - self.imageScrollView.center = point; | ||
| 407 | - | ||
| 408 | - self.yb_hideToolViews(YES); | ||
| 409 | - self.yb_hideStatusBar(NO); | ||
| 410 | - self.yb_collectionView().scrollEnabled = NO; | ||
| 411 | - [self hideTailoringImageView]; | ||
| 412 | - | ||
| 413 | - _interacting = YES; | ||
| 414 | - } | ||
| 415 | - } | ||
| 416 | -} | ||
| 417 | - | ||
| 418 | -- (void)restoreInteractionWithDuration:(NSTimeInterval)duration { | ||
| 419 | - CGSize containerSize = self.yb_containerSize(self.yb_currentOrientation()); | ||
| 420 | - | ||
| 421 | - void (^animations)(void) = ^{ | ||
| 422 | - self.yb_backView.backgroundColor = [self.yb_backView.backgroundColor colorWithAlphaComponent:1]; | ||
| 423 | - | ||
| 424 | - CGPoint anchorPoint = self.imageScrollView.layer.anchorPoint; | ||
| 425 | - self.imageScrollView.center = CGPointMake(containerSize.width * anchorPoint.x, containerSize.height * anchorPoint.y); | ||
| 426 | - self.imageScrollView.transform = CGAffineTransformIdentity; | ||
| 427 | - }; | ||
| 428 | - void (^completion)(BOOL finished) = ^(BOOL finished){ | ||
| 429 | - self.imageScrollView.layer.anchorPoint = CGPointMake(0.5, 0.5); | ||
| 430 | - self.imageScrollView.center = CGPointMake(containerSize.width * 0.5, containerSize.height * 0.5); | ||
| 431 | - self.imageScrollView.userInteractionEnabled = YES; | ||
| 432 | - self.imageScrollView.scrollEnabled = YES; | ||
| 433 | - | ||
| 434 | - self.yb_hideToolViews(NO); | ||
| 435 | - self.yb_hideStatusBar(YES); | ||
| 436 | - self.yb_collectionView().scrollEnabled = YES; | ||
| 437 | - [self cuttingImage]; | ||
| 438 | - | ||
| 439 | - self->_interactStartPoint = CGPointZero; | ||
| 440 | - self->_interacting = NO; | ||
| 441 | - }; | ||
| 442 | - | ||
| 443 | - if (duration <= 0) { | ||
| 444 | - animations(); | ||
| 445 | - completion(NO); | ||
| 446 | - } else { | ||
| 447 | - [UIView animateWithDuration:duration animations:animations completion:completion]; | ||
| 448 | - } | ||
| 449 | -} | ||
| 450 | - | ||
| 451 | -#pragma mark - <UIScrollViewDelegate> | ||
| 452 | - | ||
| 453 | -- (void)scrollViewDidZoom:(UIScrollView *)scrollView { | ||
| 454 | - YBIBImageData *data = self.yb_cellData; | ||
| 455 | - if (data.imageDidZoomBlock) { | ||
| 456 | - data.imageDidZoomBlock(data, scrollView); | ||
| 457 | - } | ||
| 458 | - | ||
| 459 | - CGRect imageViewFrame = self.imageScrollView.imageView.frame; | ||
| 460 | - CGFloat width = imageViewFrame.size.width, | ||
| 461 | - height = imageViewFrame.size.height, | ||
| 462 | - sHeight = scrollView.bounds.size.height, | ||
| 463 | - sWidth = scrollView.bounds.size.width; | ||
| 464 | - if (height > sHeight) { | ||
| 465 | - imageViewFrame.origin.y = 0; | ||
| 466 | - } else { | ||
| 467 | - imageViewFrame.origin.y = (sHeight - height) / 2.0; | ||
| 468 | - } | ||
| 469 | - if (width > sWidth) { | ||
| 470 | - imageViewFrame.origin.x = 0; | ||
| 471 | - } else { | ||
| 472 | - imageViewFrame.origin.x = (sWidth - width) / 2.0; | ||
| 473 | - } | ||
| 474 | - self.imageScrollView.imageView.frame = imageViewFrame; | ||
| 475 | -} | ||
| 476 | - | ||
| 477 | -- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { | ||
| 478 | - return self.imageScrollView.imageView; | ||
| 479 | -} | ||
| 480 | - | ||
| 481 | -- (void)scrollViewDidScroll:(UIScrollView *)scrollView { | ||
| 482 | - YBIBImageData *data = self.yb_cellData; | ||
| 483 | - if (data.imageDidScrollBlock) { | ||
| 484 | - data.imageDidScrollBlock(data, scrollView); | ||
| 485 | - } | ||
| 486 | - | ||
| 487 | - [self cuttingImage]; | ||
| 488 | -} | ||
| 489 | - | ||
| 490 | -- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view { | ||
| 491 | - [self hideTailoringImageView]; | ||
| 492 | -} | ||
| 493 | - | ||
| 494 | -- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { | ||
| 495 | - [self hideTailoringImageView]; | ||
| 496 | -} | ||
| 497 | - | ||
| 498 | -#pragma mark - <UIGestureRecognizerDelegate> | ||
| 499 | - | ||
| 500 | -- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { | ||
| 501 | - return YES; | ||
| 502 | -} | ||
| 503 | - | ||
| 504 | -#pragma mark - getters | ||
| 505 | - | ||
| 506 | -- (YBIBImageScrollView *)imageScrollView { | ||
| 507 | - if (!_imageScrollView) { | ||
| 508 | - _imageScrollView = [YBIBImageScrollView new]; | ||
| 509 | - _imageScrollView.delegate = self; | ||
| 510 | - } | ||
| 511 | - return _imageScrollView; | ||
| 512 | -} | ||
| 513 | - | ||
| 514 | -- (UIImageView *)tailoringImageView { | ||
| 515 | - if (!_tailoringImageView) { | ||
| 516 | - _tailoringImageView = [UIImageView new]; | ||
| 517 | - _tailoringImageView.contentMode = UIViewContentModeScaleAspectFit; | ||
| 518 | - } | ||
| 519 | - return _tailoringImageView; | ||
| 520 | -} | ||
| 521 | - | ||
| 522 | -@end |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Image/YBIBImageData+Internal.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBImageData+Internal.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/12. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBImageData.h" | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | -typedef NS_ENUM(NSInteger, YBIBImageLoadingStatus) { | ||
| 14 | - YBIBImageLoadingStatusNone, | ||
| 15 | - YBIBImageLoadingStatusCompressing, | ||
| 16 | - YBIBImageLoadingStatusDecoding, | ||
| 17 | - YBIBImageLoadingStatusQuerying, | ||
| 18 | - YBIBImageLoadingStatusProcessing, | ||
| 19 | - YBIBImageLoadingStatusDownloading, | ||
| 20 | - YBIBImageLoadingStatusReadingPHAsset, | ||
| 21 | -}; | ||
| 22 | - | ||
| 23 | -@class YBIBImageData; | ||
| 24 | - | ||
| 25 | -@protocol YBIBImageDataDelegate <NSObject> | ||
| 26 | -@required | ||
| 27 | - | ||
| 28 | -- (void)yb_imageData:(YBIBImageData *)data startLoadingWithStatus:(YBIBImageLoadingStatus)status; | ||
| 29 | - | ||
| 30 | -- (void)yb_imageIsInvalidForData:(YBIBImageData *)data; | ||
| 31 | - | ||
| 32 | -- (void)yb_imageData:(YBIBImageData *)data readyForImage:(__kindof UIImage *)image; | ||
| 33 | - | ||
| 34 | -- (void)yb_imageData:(YBIBImageData *)data readyForThumbImage:(__kindof UIImage *)image; | ||
| 35 | - | ||
| 36 | -- (void)yb_imageData:(YBIBImageData *)data readyForCompressedImage:(__kindof UIImage *)image; | ||
| 37 | - | ||
| 38 | -- (void)yb_imageData:(YBIBImageData *)data downloadProgress:(CGFloat)progress; | ||
| 39 | - | ||
| 40 | -- (void)yb_imageDownloadFailedForData:(YBIBImageData *)data; | ||
| 41 | - | ||
| 42 | -@end | ||
| 43 | - | ||
| 44 | -@interface YBIBImageData () | ||
| 45 | - | ||
| 46 | -@property (nonatomic, weak) id<YBIBImageDataDelegate> delegate; | ||
| 47 | - | ||
| 48 | -/// The status of asynchronous tasks. | ||
| 49 | -@property (nonatomic, assign) YBIBImageLoadingStatus loadingStatus; | ||
| 50 | - | ||
| 51 | -/// The origin image. | ||
| 52 | -@property (nonatomic, strong) UIImage *originImage; | ||
| 53 | - | ||
| 54 | -/// The image compressed by 'originImage' if need. | ||
| 55 | -@property (nonatomic, strong) UIImage *compressedImage; | ||
| 56 | - | ||
| 57 | -- (BOOL)shouldCompress; | ||
| 58 | - | ||
| 59 | -- (void)cuttingImageToRect:(CGRect)rect complete:(void(^)(UIImage * _Nullable image))complete; | ||
| 60 | - | ||
| 61 | -@end | ||
| 62 | - | ||
| 63 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Image/YBIBImageData.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBImageData.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/5. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import <Photos/Photos.h> | ||
| 10 | -#import "YBIBDataProtocol.h" | ||
| 11 | -#import "YBIBImageLayout.h" | ||
| 12 | -#import "YBIBImageCache.h" | ||
| 13 | -#import "YBIBInteractionProfile.h" | ||
| 14 | - | ||
| 15 | -NS_ASSUME_NONNULL_BEGIN | ||
| 16 | - | ||
| 17 | -@class YBIBImageData; | ||
| 18 | - | ||
| 19 | -/// 获取 NSData 的闭包 | ||
| 20 | -typedef NSData * _Nullable (^YBIBImageDataBlock)(void); | ||
| 21 | - | ||
| 22 | -/// 获取 UIImage 的闭包 | ||
| 23 | -typedef UIImage * _Nullable (^YBIBImageBlock)(void); | ||
| 24 | - | ||
| 25 | -/// 修改 NSURLRequest 并返回的闭包 | ||
| 26 | -typedef NSURLRequest * _Nullable (^YBIBRequestModifierBlock)(YBIBImageData *imageData, NSURLRequest *request); | ||
| 27 | - | ||
| 28 | -/// 根据图片逻辑像素和 scale 判断是否需要预解码的闭包 | ||
| 29 | -typedef BOOL (^YBIBPreDecodeDecisionBlock)(YBIBImageData *imageData, CGSize imageSize, CGFloat scale); | ||
| 30 | - | ||
| 31 | -/// 修改 UIImage 并返回的闭包 | ||
| 32 | -typedef void (^YBIBImageModifierBlock)(YBIBImageData *imageData, UIImage *image, void(^completion)(UIImage *processedImage)); | ||
| 33 | - | ||
| 34 | -/// 单击事件的处理闭包 | ||
| 35 | -typedef void (^YBIBImageSingleTouchBlock)(YBIBImageData *imageData); | ||
| 36 | - | ||
| 37 | -/// 内部图片滚动视图状态回调闭包 | ||
| 38 | -typedef void (^YBIBImageScrollViewStatusBlock)(YBIBImageData *imageData, UIScrollView *scrollView); | ||
| 39 | - | ||
| 40 | - | ||
| 41 | -/** | ||
| 42 | - 图片数据类,承担配置数据和处理数据的责任 | ||
| 43 | - */ | ||
| 44 | -@interface YBIBImageData : NSObject <YBIBDataProtocol> | ||
| 45 | - | ||
| 46 | -/// 本地图片名字 | ||
| 47 | -@property (nonatomic, copy, nullable) NSString *imageName; | ||
| 48 | - | ||
| 49 | -/// 本地图片路径 | ||
| 50 | -@property (nonatomic, copy, nullable) NSString *imagePath; | ||
| 51 | - | ||
| 52 | -/// 本地图片字节码,返回 NSData | ||
| 53 | -@property (nonatomic, copy, nullable) YBIBImageDataBlock imageData; | ||
| 54 | - | ||
| 55 | -/// 本地图片,返回 UIImage 及其衍生类 (若不是遵循'YYAnimatedImage'协议的类型,将失去对动图和拓展格式的支持) | ||
| 56 | -@property (nonatomic, copy, nullable) YBIBImageBlock image; | ||
| 57 | - | ||
| 58 | -/// 网络图片资源 | ||
| 59 | -@property (nonatomic, copy, nullable) NSURL *imageURL; | ||
| 60 | - | ||
| 61 | -/// 修改 NSURLRequest 并返回 | ||
| 62 | -@property (nonatomic, copy, nullable) YBIBRequestModifierBlock requestModifier; | ||
| 63 | - | ||
| 64 | -/// 相册图片资源 | ||
| 65 | -@property (nonatomic, strong, nullable) PHAsset *imagePHAsset; | ||
| 66 | - | ||
| 67 | -/// 投影视图,当前数据模型对应外界业务的 UIView (通常为 UIImageView),做转场动效用 | ||
| 68 | -@property (nonatomic, weak, nullable) __kindof UIView *projectiveView; | ||
| 69 | - | ||
| 70 | -/// 预览图/缩约图,注意若这个图片过大会导致内存压力(若 projectiveView 存在且是 UIImageView 类型将会自动获取缩约图) | ||
| 71 | -@property (nonatomic, strong, nullable) UIImage *thumbImage; | ||
| 72 | - | ||
| 73 | -/// 预览图/缩约图 URL,缓存中未找到则忽略(若 projectiveView 存在且是 UIImageView 类型将会自动获取缩约图) | ||
| 74 | -@property (nonatomic, copy, nullable) NSURL *thumbURL; | ||
| 75 | - | ||
| 76 | -/// 是否允许保存到相册 | ||
| 77 | -@property (nonatomic, assign) BOOL allowSaveToPhotoAlbum; | ||
| 78 | - | ||
| 79 | -/// 根据图片信息判断是否需要预解码 | ||
| 80 | -@property (nonatomic, copy, nullable) YBIBPreDecodeDecisionBlock preDecodeDecision; | ||
| 81 | - | ||
| 82 | -/// 是否异步预解码,默认为 YES | ||
| 83 | -@property (nonatomic, assign) BOOL shouldPreDecodeAsync; | ||
| 84 | - | ||
| 85 | -/// 压缩物理像素界限大小,当图片超过这个值将会被压缩显示,默认为 4096*4096 | ||
| 86 | -@property (nonatomic, assign) CGFloat compressingSize; | ||
| 87 | - | ||
| 88 | -/// 触发裁剪的缩放比例,必须大于等于 1,默认情况内部会动态计算 (仅当图片需要压缩显示时有效) | ||
| 89 | -@property (nonatomic, assign) CGFloat cuttingZoomScale; | ||
| 90 | - | ||
| 91 | -/** | ||
| 92 | - 判断图片是否需要压缩显示 | ||
| 93 | - */ | ||
| 94 | -- (BOOL)shouldCompressWithImage:(UIImage *)image; | ||
| 95 | - | ||
| 96 | -/** | ||
| 97 | - 修改原始图片并返回处理后的图片 (特别注意当 image 是大图的时候,避免 OOM) | ||
| 98 | - Example: | ||
| 99 | - [... setImageModifier:^(YBIBImageData *imageData, UIImage * _Nonnull image, void (^ _Nonnull completion)(UIImage * _Nonnull)) { | ||
| 100 | - //step 1 : Add watermark, trademark, etc. (Sync or async). | ||
| 101 | - ... processing code ... | ||
| 102 | - //step 2 : Return the processed UIImage. | ||
| 103 | - completion(image); | ||
| 104 | - }]; | ||
| 105 | - */ | ||
| 106 | -@property (nonatomic, copy, nullable) YBIBImageModifierBlock originImageModifier; | ||
| 107 | - | ||
| 108 | -/// 修改压缩图片并返回处理后的图片 (仅在当前图片需要被压缩时有效) | ||
| 109 | -@property (nonatomic, copy, nullable) YBIBImageModifierBlock compressedImageModifier; | ||
| 110 | - | ||
| 111 | -/// 修改裁剪图片并返回处理后的图片 (仅在当前图片需要被裁剪时有效) | ||
| 112 | -@property (nonatomic, copy, nullable) YBIBImageModifierBlock cuttedImageModifier; | ||
| 113 | - | ||
| 114 | -/// 预留属性可随意使用 | ||
| 115 | -@property (nonatomic, strong, nullable) id extraData; | ||
| 116 | - | ||
| 117 | -/// 手势交互动效配置文件 | ||
| 118 | -@property (nonatomic, strong) YBIBInteractionProfile *interactionProfile; | ||
| 119 | - | ||
| 120 | -/// 单击的处理,默认是退出图片浏览器 | ||
| 121 | -@property (nonatomic, copy, nullable) YBIBImageSingleTouchBlock singleTouchBlock; | ||
| 122 | - | ||
| 123 | -/// 图片滚动的回调 | ||
| 124 | -@property (nonatomic, copy, nullable) YBIBImageScrollViewStatusBlock imageDidScrollBlock; | ||
| 125 | - | ||
| 126 | -/// 图片缩放的回调 | ||
| 127 | -@property (nonatomic, copy, nullable) YBIBImageScrollViewStatusBlock imageDidZoomBlock; | ||
| 128 | - | ||
| 129 | -/// 图片布局类 (赋值可自定义) | ||
| 130 | -@property (nonatomic, strong) id<YBIBImageLayout> layout; | ||
| 131 | -/// 默认图片布局类 (可配置其属性) | ||
| 132 | -@property (nonatomic, weak, readonly) YBIBImageLayout *defaultLayout; | ||
| 133 | - | ||
| 134 | -/** | ||
| 135 | - 终止处理数据程序 | ||
| 136 | - */ | ||
| 137 | -- (void)stopLoading; | ||
| 138 | - | ||
| 139 | -/** | ||
| 140 | - 清除缓存的数据 | ||
| 141 | - */ | ||
| 142 | -- (void)clearCache; | ||
| 143 | - | ||
| 144 | -/** | ||
| 145 | - 加载数据,一般不需要调用这个方法,当该数据对象做了数据更新时调用 | ||
| 146 | - */ | ||
| 147 | -- (void)loadData; | ||
| 148 | - | ||
| 149 | -/// 处理后的原始图片 | ||
| 150 | -@property (nonatomic, strong, readonly) UIImage *originImage; | ||
| 151 | - | ||
| 152 | -/// 处理后的压缩图片 | ||
| 153 | -@property (nonatomic, strong, readonly) UIImage *compressedImage; | ||
| 154 | - | ||
| 155 | -@end | ||
| 156 | - | ||
| 157 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Image/YBIBImageData.m deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBImageData.m | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/5. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBImage.h" | ||
| 10 | -#import "YBIBImageData.h" | ||
| 11 | -#import "YBIBImageCell.h" | ||
| 12 | -#import "YBIBPhotoAlbumManager.h" | ||
| 13 | -#import "YBIBImageData+Internal.h" | ||
| 14 | -#import "YBIBUtilities.h" | ||
| 15 | -#import "YBIBImageCache+Internal.h" | ||
| 16 | -#import "YBIBSentinel.h" | ||
| 17 | -#import "YBIBCopywriter.h" | ||
| 18 | -#import <AssetsLibrary/AssetsLibrary.h> | ||
| 19 | - | ||
| 20 | -extern CGImageRef YYCGImageCreateDecodedCopy(CGImageRef imageRef, BOOL decodeForDisplay); | ||
| 21 | - | ||
| 22 | -static dispatch_queue_t YBIBImageProcessingQueue(void) { | ||
| 23 | - static dispatch_queue_t queue; | ||
| 24 | - static dispatch_once_t onceToken; | ||
| 25 | - dispatch_once(&onceToken, ^{ | ||
| 26 | - queue = dispatch_queue_create("com.yangbo.imagebrowser.imageprocessing", DISPATCH_QUEUE_CONCURRENT); | ||
| 27 | - }); | ||
| 28 | - return queue; | ||
| 29 | -} | ||
| 30 | - | ||
| 31 | -@implementation YBIBImageData { | ||
| 32 | - __weak id _downloadToken; | ||
| 33 | - YBIBSentinel *_cuttingSentinel; | ||
| 34 | - /// Stop processing tasks when in freeze. | ||
| 35 | - BOOL _freezing; | ||
| 36 | -} | ||
| 37 | - | ||
| 38 | -#pragma mark - life cycle | ||
| 39 | - | ||
| 40 | -- (void)dealloc { | ||
| 41 | - if (_downloadToken && [self.yb_webImageMediator() respondsToSelector:@selector(yb_cancelTaskWithDownloadToken:)]) { | ||
| 42 | - [self.yb_webImageMediator() yb_cancelTaskWithDownloadToken:_downloadToken]; | ||
| 43 | - } | ||
| 44 | - [self.imageCache removeForKey:self.cacheKey]; | ||
| 45 | -} | ||
| 46 | - | ||
| 47 | -- (instancetype)init { | ||
| 48 | - self = [super init]; | ||
| 49 | - if (self) { | ||
| 50 | - [self initValue]; | ||
| 51 | - } | ||
| 52 | - return self; | ||
| 53 | -} | ||
| 54 | - | ||
| 55 | -- (void)initValue { | ||
| 56 | - _defaultLayout = _layout = [YBIBImageLayout new]; | ||
| 57 | - _loadingStatus = YBIBImageLoadingStatusNone; | ||
| 58 | - _compressingSize = 4096 * 4096; | ||
| 59 | - _shouldPreDecodeAsync = YES; | ||
| 60 | - _freezing = NO; | ||
| 61 | - _cuttingSentinel = [YBIBSentinel new]; | ||
| 62 | - _interactionProfile = [YBIBInteractionProfile new]; | ||
| 63 | - _allowSaveToPhotoAlbum = YES; | ||
| 64 | -} | ||
| 65 | - | ||
| 66 | -#pragma mark - load data | ||
| 67 | - | ||
| 68 | -- (void)loadData { | ||
| 69 | - _freezing = NO; | ||
| 70 | - | ||
| 71 | - // Avoid handling asynchronous tasks repeatedly. | ||
| 72 | - if (self.loadingStatus != YBIBImageLoadingStatusNone) { | ||
| 73 | - [self loadThumbImage]; | ||
| 74 | - self.loadingStatus = self.loadingStatus; | ||
| 75 | - return; | ||
| 76 | - } | ||
| 77 | - | ||
| 78 | - if (self.originImage) { | ||
| 79 | - [self loadOriginImage]; | ||
| 80 | - } else if (self.imageName || self.imagePath || self.imageData) { | ||
| 81 | - [self loadYBImage]; | ||
| 82 | - } else if (self.image) { | ||
| 83 | - [self loadImageBlock]; | ||
| 84 | - } else if (self.imageURL) { | ||
| 85 | - [self loadThumbImage]; | ||
| 86 | - [self loadURL]; | ||
| 87 | - } else if (self.imagePHAsset) { | ||
| 88 | - [self loadThumbImage]; | ||
| 89 | - [self loadPHAsset]; | ||
| 90 | - } else { | ||
| 91 | - [self.delegate yb_imageIsInvalidForData:self]; | ||
| 92 | - } | ||
| 93 | -} | ||
| 94 | - | ||
| 95 | -- (void)loadOriginImage { | ||
| 96 | - if (_freezing) return; | ||
| 97 | - if (!self.originImage) return; | ||
| 98 | - | ||
| 99 | - if ([self shouldCompress]) { | ||
| 100 | - if (self.compressedImage) { | ||
| 101 | - [self.delegate yb_imageData:self readyForCompressedImage:self.compressedImage]; | ||
| 102 | - } else { | ||
| 103 | - [self loadThumbImage]; | ||
| 104 | - [self loadOriginImage_compress]; | ||
| 105 | - } | ||
| 106 | - } else { | ||
| 107 | - [self.delegate yb_imageData:self readyForImage:self.originImage]; | ||
| 108 | - } | ||
| 109 | -} | ||
| 110 | -- (void)loadOriginImage_compress { | ||
| 111 | - if (_freezing) return; | ||
| 112 | - if (!self.originImage) return; | ||
| 113 | - | ||
| 114 | - self.loadingStatus = YBIBImageLoadingStatusCompressing; | ||
| 115 | - __weak typeof(self) wSelf = self; | ||
| 116 | - CGSize size = [self bestSizeOfCompressing]; | ||
| 117 | - | ||
| 118 | - YBIB_DISPATCH_ASYNC(YBIBImageProcessingQueue(), ^{ | ||
| 119 | - if (self->_freezing) { | ||
| 120 | - self.loadingStatus = YBIBImageLoadingStatusNone; | ||
| 121 | - return; | ||
| 122 | - } | ||
| 123 | - // Ensure the best display effect. | ||
| 124 | - UIGraphicsBeginImageContextWithOptions(size, NO, UIScreen.mainScreen.scale); | ||
| 125 | - [self.originImage drawInRect:CGRectMake(0, 0, size.width, size.height)]; | ||
| 126 | - if (self->_freezing) { | ||
| 127 | - UIGraphicsEndImageContext(); | ||
| 128 | - self.loadingStatus = YBIBImageLoadingStatusNone; | ||
| 129 | - return; | ||
| 130 | - } | ||
| 131 | - UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext(); | ||
| 132 | - UIGraphicsEndImageContext(); | ||
| 133 | - | ||
| 134 | - YBIB_DISPATCH_ASYNC_MAIN(^{ | ||
| 135 | - __strong typeof(wSelf) self = wSelf; | ||
| 136 | - if (!self) return; | ||
| 137 | - | ||
| 138 | - self.loadingStatus = YBIBImageLoadingStatusNone; | ||
| 139 | - | ||
| 140 | - [self modifyImageWithModifier:self.compressedImageModifier image:resultImage completion:^(UIImage *processedImage) { | ||
| 141 | - __strong typeof(wSelf) self = wSelf; | ||
| 142 | - if (!self) return; | ||
| 143 | - self.compressedImage = processedImage ?: self.originImage; | ||
| 144 | - [self.delegate yb_imageData:self readyForCompressedImage:self.compressedImage]; | ||
| 145 | - }]; | ||
| 146 | - }) | ||
| 147 | - }) | ||
| 148 | -} | ||
| 149 | - | ||
| 150 | -- (void)loadYBImage { | ||
| 151 | - if (_freezing) return; | ||
| 152 | - NSString *name = self.imageName.copy; | ||
| 153 | - NSString *path = self.imagePath.copy; | ||
| 154 | - NSData *data = self.imageData ? self.imageData().copy : nil; | ||
| 155 | - if (name.length == 0 && path.length == 0 && data.length == 0) return; | ||
| 156 | - | ||
| 157 | - YBImageDecodeDecision decision = [self defaultDecodeDecision]; | ||
| 158 | - | ||
| 159 | - __block YBImage *image; | ||
| 160 | - __weak typeof(self) wSelf = self; | ||
| 161 | - void(^dealBlock)(void) = ^{ | ||
| 162 | - if (name.length > 0) { | ||
| 163 | - image = [YBImage imageNamed:name decodeDecision:decision]; | ||
| 164 | - } else if (path.length > 0) { | ||
| 165 | - image = [YBImage imageWithContentsOfFile:path decodeDecision:decision]; | ||
| 166 | - } else if (data.length > 0) { | ||
| 167 | - image = [YBImage imageWithData:data scale:UIScreen.mainScreen.scale decodeDecision:decision]; | ||
| 168 | - } | ||
| 169 | - YBIB_DISPATCH_ASYNC_MAIN(^{ | ||
| 170 | - __strong typeof(wSelf) self = wSelf; | ||
| 171 | - if (!self) return; | ||
| 172 | - self.loadingStatus = YBIBImageLoadingStatusNone; | ||
| 173 | - if (image) { | ||
| 174 | - [self setOriginImageAndLoadWithImage:image]; | ||
| 175 | - } else { | ||
| 176 | - [self.delegate yb_imageIsInvalidForData:self]; | ||
| 177 | - } | ||
| 178 | - }) | ||
| 179 | - }; | ||
| 180 | - | ||
| 181 | - if (self.shouldPreDecodeAsync) { | ||
| 182 | - [self loadThumbImage]; | ||
| 183 | - self.loadingStatus = YBIBImageLoadingStatusDecoding; | ||
| 184 | - YBIB_DISPATCH_ASYNC(YBIBImageProcessingQueue(), dealBlock) | ||
| 185 | - } else { | ||
| 186 | - self.loadingStatus = YBIBImageLoadingStatusDecoding; | ||
| 187 | - dealBlock(); | ||
| 188 | - } | ||
| 189 | -} | ||
| 190 | - | ||
| 191 | -- (void)loadImageBlock { | ||
| 192 | - if (_freezing) return; | ||
| 193 | - __block UIImage *image = self.image ? self.image() : nil; | ||
| 194 | - if (!image) return; | ||
| 195 | - | ||
| 196 | - BOOL shouldPreDecode = self.preDecodeDecision ? self.preDecodeDecision(self, image.size, image.scale) : ![self shouldCompressWithImage:image]; | ||
| 197 | - | ||
| 198 | - __weak typeof(self) wSelf = self; | ||
| 199 | - void(^dealBlock)(void) = ^{ | ||
| 200 | - // Do not need to decode If 'image' conformed 'YYAnimatedImage'. (Not entirely accurate.) | ||
| 201 | - if (![image conformsToProtocol:@protocol(YYAnimatedImage)]) { | ||
| 202 | - CGImageRef cgImage = YYCGImageCreateDecodedCopy(image.CGImage, shouldPreDecode); | ||
| 203 | - image = [UIImage imageWithCGImage:cgImage scale:image.scale orientation:image.imageOrientation]; | ||
| 204 | - if (cgImage) CGImageRelease(cgImage); | ||
| 205 | - } | ||
| 206 | - YBIB_DISPATCH_ASYNC_MAIN(^{ | ||
| 207 | - __strong typeof(wSelf) self = wSelf; | ||
| 208 | - if (!self) return; | ||
| 209 | - self.loadingStatus = YBIBImageLoadingStatusNone; | ||
| 210 | - [self setOriginImageAndLoadWithImage:image]; | ||
| 211 | - }) | ||
| 212 | - }; | ||
| 213 | - | ||
| 214 | - if (self.shouldPreDecodeAsync) { | ||
| 215 | - [self loadThumbImage]; | ||
| 216 | - self.loadingStatus = YBIBImageLoadingStatusDecoding; | ||
| 217 | - YBIB_DISPATCH_ASYNC(YBIBImageProcessingQueue(), dealBlock) | ||
| 218 | - } else { | ||
| 219 | - self.loadingStatus = YBIBImageLoadingStatusDecoding; | ||
| 220 | - dealBlock(); | ||
| 221 | - } | ||
| 222 | -} | ||
| 223 | - | ||
| 224 | -- (void)loadURL { | ||
| 225 | - if (!self.imageURL || self.imageURL.absoluteString.length == 0) return; | ||
| 226 | - [self loadURL_queryCache]; | ||
| 227 | -} | ||
| 228 | -- (void)loadURL_queryCache { | ||
| 229 | - if (_freezing) return; | ||
| 230 | - if (!self.imageURL || self.imageURL.absoluteString.length == 0) return; | ||
| 231 | - | ||
| 232 | - YBImageDecodeDecision decision = [self defaultDecodeDecision]; | ||
| 233 | - | ||
| 234 | - self.loadingStatus = YBIBImageLoadingStatusQuerying; | ||
| 235 | - [self.yb_webImageMediator() yb_queryCacheOperationForKey:self.imageURL completed:^(UIImage * _Nullable image, NSData * _Nullable imageData) { | ||
| 236 | - if (!imageData || imageData.length == 0) { | ||
| 237 | - YBIB_DISPATCH_ASYNC_MAIN(^{ | ||
| 238 | - self.loadingStatus = YBIBImageLoadingStatusNone; | ||
| 239 | - [self loadURL_download]; | ||
| 240 | - }) | ||
| 241 | - return; | ||
| 242 | - } | ||
| 243 | - | ||
| 244 | - YBIB_DISPATCH_ASYNC(YBIBImageProcessingQueue(), ^{ | ||
| 245 | - if (self->_freezing) { | ||
| 246 | - self.loadingStatus = YBIBImageLoadingStatusNone; | ||
| 247 | - return; | ||
| 248 | - } | ||
| 249 | - YBImage *image = [YBImage imageWithData:imageData scale:UIScreen.mainScreen.scale decodeDecision:decision]; | ||
| 250 | - __weak typeof(self) wSelf = self; | ||
| 251 | - YBIB_DISPATCH_ASYNC_MAIN(^{ | ||
| 252 | - __strong typeof(wSelf) self = wSelf; | ||
| 253 | - if (!self) return; | ||
| 254 | - self.loadingStatus = YBIBImageLoadingStatusNone; | ||
| 255 | - if (image) { // Maybe the image data is invalid. | ||
| 256 | - [self setOriginImageAndLoadWithImage:image]; | ||
| 257 | - } else { | ||
| 258 | - [self loadURL_download]; | ||
| 259 | - } | ||
| 260 | - }) | ||
| 261 | - }) | ||
| 262 | - }]; | ||
| 263 | -} | ||
| 264 | -- (void)loadURL_download { | ||
| 265 | - if (_freezing) return; | ||
| 266 | - if (!self.imageURL || self.imageURL.absoluteString.length == 0) return; | ||
| 267 | - | ||
| 268 | - YBImageDecodeDecision decision = [self defaultDecodeDecision]; | ||
| 269 | - | ||
| 270 | - self.loadingStatus = YBIBImageLoadingStatusDownloading; | ||
| 271 | - __weak typeof(self) wSelf = self; | ||
| 272 | - _downloadToken = [self.yb_webImageMediator() yb_downloadImageWithURL:self.imageURL requestModifier:^NSURLRequest * _Nullable(NSURLRequest * _Nonnull request) { | ||
| 273 | - return self.requestModifier ? self.requestModifier(self, request) : request; | ||
| 274 | - } progress:^(NSInteger receivedSize, NSInteger expectedSize) { | ||
| 275 | - CGFloat progress = receivedSize * 1.0 / expectedSize ?: 0; | ||
| 276 | - YBIB_DISPATCH_ASYNC_MAIN(^{ | ||
| 277 | - __strong typeof(wSelf) self = wSelf; | ||
| 278 | - if (!self) return; | ||
| 279 | - [self.delegate yb_imageData:self downloadProgress:progress]; | ||
| 280 | - }) | ||
| 281 | - } success:^(NSData * _Nullable imageData, BOOL finished) { | ||
| 282 | - if (!finished) return; | ||
| 283 | - | ||
| 284 | - YBIB_DISPATCH_ASYNC(YBIBImageProcessingQueue(), ^{ | ||
| 285 | - if (self->_freezing) { | ||
| 286 | - self.loadingStatus = YBIBImageLoadingStatusNone; | ||
| 287 | - return; | ||
| 288 | - } | ||
| 289 | - YBImage *image = [YBImage imageWithData:imageData scale:UIScreen.mainScreen.scale decodeDecision:decision]; | ||
| 290 | - YBIB_DISPATCH_ASYNC_MAIN(^{ | ||
| 291 | - __strong typeof(wSelf) self = wSelf; | ||
| 292 | - if (!self) return; | ||
| 293 | - [self.yb_webImageMediator() yb_storeToDiskWithImageData:imageData forKey:self.imageURL]; | ||
| 294 | - self.loadingStatus = YBIBImageLoadingStatusNone; | ||
| 295 | - if (image) { | ||
| 296 | - [self setOriginImageAndLoadWithImage:image]; | ||
| 297 | - } else { | ||
| 298 | - [self.delegate yb_imageIsInvalidForData:self]; | ||
| 299 | - } | ||
| 300 | - }) | ||
| 301 | - }) | ||
| 302 | - } failed:^(NSError * _Nullable error, BOOL finished) { | ||
| 303 | - if (!finished) return; | ||
| 304 | - __strong typeof(wSelf) self = wSelf; | ||
| 305 | - if (!self) return; | ||
| 306 | - self.loadingStatus = YBIBImageLoadingStatusNone; | ||
| 307 | - [self.delegate yb_imageDownloadFailedForData:self]; | ||
| 308 | - }]; | ||
| 309 | -} | ||
| 310 | - | ||
| 311 | -- (void)loadPHAsset { | ||
| 312 | - if (_freezing) return; | ||
| 313 | - if (!self.imagePHAsset) return; | ||
| 314 | - | ||
| 315 | - YBImageDecodeDecision decision = [self defaultDecodeDecision]; | ||
| 316 | - | ||
| 317 | - self.loadingStatus = YBIBImageLoadingStatusReadingPHAsset; | ||
| 318 | - YBIB_DISPATCH_ASYNC(YBIBImageProcessingQueue(), ^{ | ||
| 319 | - [YBIBPhotoAlbumManager getImageDataWithPHAsset:self.imagePHAsset completion:^(NSData * _Nullable data) { | ||
| 320 | - if (self->_freezing) { | ||
| 321 | - self.loadingStatus = YBIBImageLoadingStatusNone; | ||
| 322 | - return; | ||
| 323 | - } | ||
| 324 | - YBImage *image = [YBImage imageWithData:data scale:UIScreen.mainScreen.scale decodeDecision:decision]; | ||
| 325 | - __weak typeof(self) wSelf = self; | ||
| 326 | - YBIB_DISPATCH_ASYNC_MAIN(^{ | ||
| 327 | - __strong typeof(wSelf) self = wSelf; | ||
| 328 | - if (!self) return; | ||
| 329 | - | ||
| 330 | - self.loadingStatus = YBIBImageLoadingStatusNone; | ||
| 331 | - if (image) { | ||
| 332 | - [self setOriginImageAndLoadWithImage:image]; | ||
| 333 | - } else { | ||
| 334 | - [self.delegate yb_imageIsInvalidForData:self]; | ||
| 335 | - } | ||
| 336 | - }) | ||
| 337 | - }]; | ||
| 338 | - }) | ||
| 339 | -} | ||
| 340 | - | ||
| 341 | -- (void)loadThumbImage { | ||
| 342 | - if (_freezing) return; | ||
| 343 | - if (self.thumbImage) { | ||
| 344 | - [self.delegate yb_imageData:self readyForThumbImage:self.thumbImage]; | ||
| 345 | - } else if (self.thumbURL) { | ||
| 346 | - __weak typeof(self) wSelf = self; | ||
| 347 | - [self.yb_webImageMediator() yb_queryCacheOperationForKey:self.thumbURL completed:^(UIImage * _Nullable image, NSData * _Nullable imageData) { | ||
| 348 | - __strong typeof(wSelf) self = wSelf; | ||
| 349 | - if (!self) return; | ||
| 350 | - | ||
| 351 | - UIImage *thumbImage; | ||
| 352 | - if (image) { | ||
| 353 | - thumbImage = image; | ||
| 354 | - } else if (imageData) { | ||
| 355 | - thumbImage = [UIImage imageWithData:imageData]; | ||
| 356 | - } | ||
| 357 | - // If the target image is ready, ignore the thumb image. | ||
| 358 | - BOOL shouldIgnore = [self shouldCompress] ? (self.compressedImage != nil) : (self.originImage != nil); | ||
| 359 | - if (!shouldIgnore && thumbImage) { | ||
| 360 | - [self.delegate yb_imageData:self readyForThumbImage:thumbImage]; | ||
| 361 | - } | ||
| 362 | - }]; | ||
| 363 | - } else if (self.projectiveView && [self.projectiveView isKindOfClass:UIImageView.self] && ((UIImageView *)self.projectiveView).image) { | ||
| 364 | - UIImage *thumbImage = ((UIImageView *)self.projectiveView).image; | ||
| 365 | - [self.delegate yb_imageData:self readyForThumbImage:thumbImage]; | ||
| 366 | - } | ||
| 367 | -} | ||
| 368 | - | ||
| 369 | -#pragma mark - internal | ||
| 370 | - | ||
| 371 | -- (void)cuttingImageToRect:(CGRect)rect complete:(void (^)(UIImage * _Nullable))complete { | ||
| 372 | - if (_freezing) return; | ||
| 373 | - if (!self.originImage) return; | ||
| 374 | - | ||
| 375 | - int32_t value = [_cuttingSentinel increase]; | ||
| 376 | - BOOL (^isCancelled)(void) = ^BOOL(void) { | ||
| 377 | - if (self->_freezing) return YES; | ||
| 378 | - return value != self->_cuttingSentinel.value; | ||
| 379 | - }; | ||
| 380 | - | ||
| 381 | - YBIB_DISPATCH_ASYNC(YBIBImageProcessingQueue(), ^{ | ||
| 382 | - if (isCancelled()) { | ||
| 383 | - complete(nil); | ||
| 384 | - return; | ||
| 385 | - } | ||
| 386 | - CGFloat scale = self.originImage.scale; | ||
| 387 | - CGFloat width = self.originImage.size.width; | ||
| 388 | - CGFloat height = self.originImage.size.height; | ||
| 389 | - | ||
| 390 | - BOOL reverseWidthHeight = NO; | ||
| 391 | - CGAffineTransform transform = CGAffineTransformIdentity; | ||
| 392 | - switch (self.originImage.imageOrientation) { | ||
| 393 | - case UIImageOrientationDown: | ||
| 394 | - case UIImageOrientationDownMirrored: | ||
| 395 | - CGAffineTransformTranslate(CGAffineTransformMakeRotation(-M_PI), -width, -height); | ||
| 396 | - break; | ||
| 397 | - case UIImageOrientationLeft: | ||
| 398 | - case UIImageOrientationLeftMirrored: | ||
| 399 | - transform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(M_PI_2), 0, -height); | ||
| 400 | - reverseWidthHeight = YES; | ||
| 401 | - break; | ||
| 402 | - case UIImageOrientationRight: | ||
| 403 | - case UIImageOrientationRightMirrored: | ||
| 404 | - transform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(-M_PI_2), -width, 0); | ||
| 405 | - reverseWidthHeight = YES; | ||
| 406 | - break; | ||
| 407 | - default: break; | ||
| 408 | - } | ||
| 409 | - transform = CGAffineTransformScale(transform, scale, scale); | ||
| 410 | - CGRect correctRect = CGRectApplyAffineTransform(rect, transform); | ||
| 411 | - CGImageRef cgImage = CGImageCreateWithImageInRect(self.originImage.CGImage, correctRect); | ||
| 412 | - | ||
| 413 | - if (isCancelled()) { | ||
| 414 | - complete(nil); | ||
| 415 | - if (cgImage) CGImageRelease(cgImage); | ||
| 416 | - return; | ||
| 417 | - } | ||
| 418 | - CGFloat cgWidth = reverseWidthHeight ? CGImageGetHeight(cgImage) : CGImageGetWidth(cgImage); | ||
| 419 | - CGFloat cgHeight = reverseWidthHeight ? CGImageGetWidth(cgImage) : CGImageGetHeight(cgImage); | ||
| 420 | - CGSize size = [self bestSizeOfCuttingWithOriginSize:CGSizeMake(cgWidth / scale, cgHeight / scale)]; | ||
| 421 | - UIImage *tmpImage = [UIImage imageWithCGImage:cgImage scale:self.originImage.scale orientation:self.originImage.imageOrientation]; | ||
| 422 | - if (isCancelled()) { | ||
| 423 | - complete(nil); | ||
| 424 | - if (cgImage) CGImageRelease(cgImage); | ||
| 425 | - return; | ||
| 426 | - } | ||
| 427 | - | ||
| 428 | - // Ensure the best display effect. | ||
| 429 | - UIGraphicsBeginImageContextWithOptions(size, NO, UIScreen.mainScreen.scale); | ||
| 430 | - [tmpImage drawInRect:CGRectMake(0, 0, size.width, size.height)]; | ||
| 431 | - if (isCancelled()) { | ||
| 432 | - complete(nil); | ||
| 433 | - UIGraphicsEndImageContext(); | ||
| 434 | - if (cgImage) CGImageRelease(cgImage); | ||
| 435 | - return; | ||
| 436 | - } | ||
| 437 | - UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext(); | ||
| 438 | - UIGraphicsEndImageContext(); | ||
| 439 | - if (cgImage) CGImageRelease(cgImage); | ||
| 440 | - | ||
| 441 | - __weak typeof(self) wSelf = self; | ||
| 442 | - YBIB_DISPATCH_ASYNC_MAIN(^{ | ||
| 443 | - __strong typeof(wSelf) self = wSelf; | ||
| 444 | - if (!self) return; | ||
| 445 | - | ||
| 446 | - [self modifyImageWithModifier:self.cuttedImageModifier image:resultImage completion:^(UIImage *image) { | ||
| 447 | - __strong typeof(wSelf) self = wSelf; | ||
| 448 | - if (!self) return; | ||
| 449 | - complete(image); | ||
| 450 | - }]; | ||
| 451 | - }) | ||
| 452 | - }) | ||
| 453 | -} | ||
| 454 | - | ||
| 455 | -- (BOOL)shouldCompress { | ||
| 456 | - return [self shouldCompressWithImage:self.originImage]; | ||
| 457 | -} | ||
| 458 | - | ||
| 459 | -#pragma mark - public | ||
| 460 | - | ||
| 461 | -- (BOOL)shouldCompressWithImage:(UIImage *)image { | ||
| 462 | - if (!image) return NO; | ||
| 463 | - return [self shouldCompressWithImageSize:image.size scale:image.scale]; | ||
| 464 | -} | ||
| 465 | - | ||
| 466 | -- (void)stopLoading { | ||
| 467 | - _freezing = YES; | ||
| 468 | - self.loadingStatus = YBIBImageLoadingStatusNone; | ||
| 469 | -} | ||
| 470 | - | ||
| 471 | -- (void)clearCache { | ||
| 472 | - [self.imageCache removeForKey:self.cacheKey]; | ||
| 473 | -} | ||
| 474 | - | ||
| 475 | -#pragma mark - private | ||
| 476 | - | ||
| 477 | -/// 'size': logic pixel. | ||
| 478 | -- (BOOL)shouldCompressWithImageSize:(CGSize)size scale:(CGFloat)scale { | ||
| 479 | - return size.width * scale * size.height * scale > self.compressingSize; | ||
| 480 | -} | ||
| 481 | - | ||
| 482 | -/// Logic pixel. | ||
| 483 | -- (CGSize)bestSizeOfCompressing { | ||
| 484 | - if (!self.originImage) return CGSizeZero; | ||
| 485 | - UIDeviceOrientation orientation = self.yb_currentOrientation(); | ||
| 486 | - CGRect imageViewFrame = [self.layout yb_imageViewFrameWithContainerSize:self.yb_containerSize(orientation) imageSize:self.originImage.size orientation:orientation]; | ||
| 487 | - return imageViewFrame.size; | ||
| 488 | -} | ||
| 489 | - | ||
| 490 | -/// Logic pixel. | ||
| 491 | -- (CGSize)bestSizeOfCuttingWithOriginSize:(CGSize)originSize { | ||
| 492 | - CGSize containerSize = self.yb_containerSize(self.yb_currentOrientation()); | ||
| 493 | - CGFloat maxWidth = containerSize.width, maxHeight = containerSize.height; | ||
| 494 | - CGFloat oWidth = originSize.width, oHeight = originSize.height; | ||
| 495 | - if (maxWidth <= 0 || maxHeight <= 0 || oWidth <= 0 || oHeight <= 0) return CGSizeZero; | ||
| 496 | - | ||
| 497 | - if (oWidth <= maxWidth && oHeight <= maxHeight) { | ||
| 498 | - return originSize; | ||
| 499 | - } | ||
| 500 | - CGFloat rWidth = 0, rHeight = 0; | ||
| 501 | - if (oWidth / maxWidth < oHeight / maxHeight) { | ||
| 502 | - rHeight = maxHeight; | ||
| 503 | - rWidth = oWidth / oHeight * rHeight; | ||
| 504 | - } else { | ||
| 505 | - rWidth = maxWidth; | ||
| 506 | - rHeight = oHeight / oWidth * rWidth; | ||
| 507 | - } | ||
| 508 | - return CGSizeMake(rWidth, rHeight); | ||
| 509 | -} | ||
| 510 | - | ||
| 511 | -- (YBImageDecodeDecision)defaultDecodeDecision { | ||
| 512 | - __weak typeof(self) wSelf = self; | ||
| 513 | - return ^BOOL(CGSize imageSize, CGFloat scale) { | ||
| 514 | - __strong typeof(wSelf) self = wSelf; | ||
| 515 | - if (!self) return NO; | ||
| 516 | - CGSize logicSize = CGSizeMake(imageSize.width / scale, imageSize.height / scale); | ||
| 517 | - if (self.preDecodeDecision) return self.preDecodeDecision(self, logicSize, scale); | ||
| 518 | - if ([self shouldCompressWithImageSize:logicSize scale:scale]) return NO; | ||
| 519 | - return YES; | ||
| 520 | - }; | ||
| 521 | -} | ||
| 522 | - | ||
| 523 | -- (void)modifyImageWithModifier:(YBIBImageModifierBlock)modifier image:(UIImage *)image completion:(void(^)(UIImage *processedImage))completion { | ||
| 524 | - if (modifier) { | ||
| 525 | - self.loadingStatus = YBIBImageLoadingStatusProcessing; | ||
| 526 | - __weak typeof(self) wSelf = self; | ||
| 527 | - modifier(self, image, ^(UIImage *processedImage){ | ||
| 528 | - // This step is necessary, maybe 'self' is already 'dealloc' if processing code takes too much time. | ||
| 529 | - __strong typeof(wSelf) self = wSelf; | ||
| 530 | - if (!self) return; | ||
| 531 | - self.loadingStatus = YBIBImageLoadingStatusNone; | ||
| 532 | - completion(processedImage); | ||
| 533 | - }); | ||
| 534 | - } else { | ||
| 535 | - completion(image); | ||
| 536 | - } | ||
| 537 | -} | ||
| 538 | - | ||
| 539 | -- (void)setOriginImageAndLoadWithImage:(UIImage *)image { | ||
| 540 | - __weak typeof(self) wSelf = self; | ||
| 541 | - [self modifyImageWithModifier:self.originImageModifier image:image completion:^(UIImage *processedImage) { | ||
| 542 | - __strong typeof(wSelf) self = wSelf; | ||
| 543 | - if (!self) return; | ||
| 544 | - self.originImage = processedImage; | ||
| 545 | - [self loadOriginImage]; | ||
| 546 | - }]; | ||
| 547 | -} | ||
| 548 | - | ||
| 549 | -- (void)saveToPhotoAlbumCompleteWithError:(nullable NSError *)error { | ||
| 550 | - if (error) { | ||
| 551 | - [self.yb_auxiliaryViewHandler() yb_showIncorrectToastWithContainer:self.yb_containerView text:[YBIBCopywriter sharedCopywriter].saveToPhotoAlbumFailed]; | ||
| 552 | - } else { | ||
| 553 | - [self.yb_auxiliaryViewHandler() yb_showCorrectToastWithContainer:self.yb_containerView text:[YBIBCopywriter sharedCopywriter].saveToPhotoAlbumSuccess]; | ||
| 554 | - } | ||
| 555 | -} | ||
| 556 | - | ||
| 557 | -- (void)UIImageWriteToSavedPhotosAlbum_completedWithImage:(UIImage *)image error:(NSError *)error context:(void *)context { | ||
| 558 | - [self saveToPhotoAlbumCompleteWithError:error]; | ||
| 559 | -} | ||
| 560 | - | ||
| 561 | -- (YBIBImageCache *)imageCache { | ||
| 562 | - return self.yb_backView.ybib_imageCache; | ||
| 563 | -} | ||
| 564 | - | ||
| 565 | -#pragma mark - <YBIBDataProtocol> | ||
| 566 | - | ||
| 567 | -@synthesize yb_isHideTransitioning = _yb_isHideTransitioning; | ||
| 568 | -@synthesize yb_currentOrientation = _yb_currentOrientation; | ||
| 569 | -@synthesize yb_containerSize = _yb_containerSize; | ||
| 570 | -@synthesize yb_containerView = _yb_containerView; | ||
| 571 | -@synthesize yb_auxiliaryViewHandler = _yb_auxiliaryViewHandler; | ||
| 572 | -@synthesize yb_webImageMediator = _yb_webImageMediator; | ||
| 573 | -@synthesize yb_backView = _yb_backView; | ||
| 574 | - | ||
| 575 | -- (nonnull Class)yb_classOfCell { | ||
| 576 | - return YBIBImageCell.self; | ||
| 577 | -} | ||
| 578 | - | ||
| 579 | -- (UIView *)yb_projectiveView { | ||
| 580 | - return self.projectiveView; | ||
| 581 | -} | ||
| 582 | - | ||
| 583 | -- (CGRect)yb_imageViewFrameWithContainerSize:(CGSize)containerSize imageSize:(CGSize)imageSize orientation:(UIDeviceOrientation)orientation { | ||
| 584 | - return [self.layout yb_imageViewFrameWithContainerSize:containerSize imageSize:imageSize orientation:orientation]; | ||
| 585 | -} | ||
| 586 | - | ||
| 587 | -- (void)yb_preload { | ||
| 588 | - if (!self.delegate) { | ||
| 589 | - [self loadData]; | ||
| 590 | - } | ||
| 591 | -} | ||
| 592 | - | ||
| 593 | -- (BOOL)yb_allowSaveToPhotoAlbum { | ||
| 594 | - return self.allowSaveToPhotoAlbum; | ||
| 595 | -} | ||
| 596 | - | ||
| 597 | -- (void)yb_saveToPhotoAlbum { | ||
| 598 | - void(^saveData)(NSData *) = ^(NSData * _Nonnull data){ | ||
| 599 | - [[ALAssetsLibrary new] writeImageDataToSavedPhotosAlbum:data metadata:nil completionBlock:^(NSURL *assetURL, NSError *error) { | ||
| 600 | - [self saveToPhotoAlbumCompleteWithError:error]; | ||
| 601 | - }]; | ||
| 602 | - }; | ||
| 603 | - void(^saveImage)(UIImage *) = ^(UIImage * _Nonnull image){ | ||
| 604 | - UIImageWriteToSavedPhotosAlbum(image, self, @selector(UIImageWriteToSavedPhotosAlbum_completedWithImage:error:context:), NULL); | ||
| 605 | - }; | ||
| 606 | - void(^unableToSave)(void) = ^(){ | ||
| 607 | - [self.yb_auxiliaryViewHandler() yb_showIncorrectToastWithContainer:self.yb_containerView text:[YBIBCopywriter sharedCopywriter].unableToSave]; | ||
| 608 | - }; | ||
| 609 | - | ||
| 610 | - [YBIBPhotoAlbumManager getPhotoAlbumAuthorizationSuccess:^{ | ||
| 611 | - if ([self.originImage conformsToProtocol:@protocol(YYAnimatedImage)] && [self.originImage respondsToSelector:@selector(animatedImageData)] && [self.originImage performSelector:@selector(animatedImageData)]) { | ||
| 612 | - NSData *data = [self.originImage performSelector:@selector(animatedImageData)]; | ||
| 613 | - data ? saveData(data) : unableToSave(); | ||
| 614 | - } else if (self.originImage) { | ||
| 615 | - saveImage(self.originImage); | ||
| 616 | - } else if (self.imageURL) { | ||
| 617 | - [self.yb_webImageMediator() yb_queryCacheOperationForKey:self.imageURL completed:^(UIImage * _Nullable image, NSData * _Nullable data) { | ||
| 618 | - if (data) { | ||
| 619 | - saveData(data); | ||
| 620 | - } else if (image) { | ||
| 621 | - saveImage(image); | ||
| 622 | - } else { | ||
| 623 | - unableToSave(); | ||
| 624 | - } | ||
| 625 | - }]; | ||
| 626 | - } else { | ||
| 627 | - unableToSave(); | ||
| 628 | - } | ||
| 629 | - } failed:^{ | ||
| 630 | - [self.yb_auxiliaryViewHandler() yb_showIncorrectToastWithContainer:self.yb_containerView text:[YBIBCopywriter sharedCopywriter].getPhotoAlbumAuthorizationFailed]; | ||
| 631 | - }]; | ||
| 632 | -} | ||
| 633 | - | ||
| 634 | -#pragma mark - getters & setters | ||
| 635 | - | ||
| 636 | -@synthesize delegate = _delegate; | ||
| 637 | -- (void)setDelegate:(id<YBIBImageDataDelegate>)delegate { | ||
| 638 | - _delegate = delegate; | ||
| 639 | - if (delegate) { | ||
| 640 | - [self loadData]; | ||
| 641 | - } else { | ||
| 642 | - _freezing = YES; | ||
| 643 | - // Remove the resident cache if '_delegate' is nil. | ||
| 644 | - [self.imageCache removeResidentForKey:self.cacheKey]; | ||
| 645 | - } | ||
| 646 | -} | ||
| 647 | -- (id<YBIBImageDataDelegate>)delegate { | ||
| 648 | - // Stop sending data to the '_delegate' if it is transiting. | ||
| 649 | - return self.yb_isHideTransitioning() ? nil : _delegate; | ||
| 650 | -} | ||
| 651 | - | ||
| 652 | -- (void)setImageURL:(NSURL *)imageURL { | ||
| 653 | - _imageURL = [imageURL isKindOfClass:NSString.class] ? [NSURL URLWithString:(NSString *)imageURL] : imageURL; | ||
| 654 | -} | ||
| 655 | - | ||
| 656 | -- (NSString *)cacheKey { | ||
| 657 | - return [NSString stringWithFormat:@"%p", self]; | ||
| 658 | -} | ||
| 659 | - | ||
| 660 | -- (void)setOriginImage:(__kindof UIImage *)originImage { | ||
| 661 | - // 'image' should be resident if '_delegate' exists. | ||
| 662 | - [self.imageCache setImage:originImage type:YBIBImageCacheTypeOrigin forKey:self.cacheKey resident:self->_delegate != nil]; | ||
| 663 | -} | ||
| 664 | -- (UIImage *)originImage { | ||
| 665 | - return [self.imageCache imageForKey:self.cacheKey type:YBIBImageCacheTypeOrigin]; | ||
| 666 | -} | ||
| 667 | - | ||
| 668 | -- (void)setCompressedImage:(UIImage *)compressedImage { | ||
| 669 | - // 'image' should be resident if '_delegate' exists. | ||
| 670 | - [self.imageCache setImage:compressedImage type:YBIBImageCacheTypeCompressed forKey:self.cacheKey resident:_delegate != nil]; | ||
| 671 | -} | ||
| 672 | -- (UIImage *)compressedImage { | ||
| 673 | - return [self.imageCache imageForKey:self.cacheKey type:YBIBImageCacheTypeCompressed]; | ||
| 674 | -} | ||
| 675 | - | ||
| 676 | -- (void)setLoadingStatus:(YBIBImageLoadingStatus)loadingStatus { | ||
| 677 | - // Ensure thread safety. | ||
| 678 | - YBIB_DISPATCH_ASYNC_MAIN(^{ | ||
| 679 | - self->_loadingStatus = loadingStatus; | ||
| 680 | - [self.delegate yb_imageData:self startLoadingWithStatus:loadingStatus]; | ||
| 681 | - }); | ||
| 682 | -} | ||
| 683 | - | ||
| 684 | -- (CGFloat)cuttingZoomScale { | ||
| 685 | - if (_cuttingZoomScale >= 1) return _cuttingZoomScale; | ||
| 686 | - _cuttingZoomScale = 1.1; | ||
| 687 | - if (!self.originImage) return _cuttingZoomScale; | ||
| 688 | - CGFloat imagePixel = self.originImage.size.width * self.originImage.size.height * self.originImage.scale * self.originImage.scale; | ||
| 689 | - // The larger the image size, the larger the '_cuttingZoomScale', in order to reduce the burden of CPU and memory. | ||
| 690 | - CGFloat scale = YBIBLowMemory() ? 0.28 : 0.19; | ||
| 691 | - _cuttingZoomScale += (imagePixel / self.compressingSize * scale); | ||
| 692 | - return _cuttingZoomScale; | ||
| 693 | -} | ||
| 694 | - | ||
| 695 | -@end |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Image/YBIBImageLayout.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBImageLayout.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/12. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import <UIKit/UIKit.h> | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | -@protocol YBIBImageLayout <NSObject> | ||
| 14 | -@required | ||
| 15 | - | ||
| 16 | -/** | ||
| 17 | - 计算图片展示的位置 | ||
| 18 | - | ||
| 19 | - @param containerSize 容器大小 | ||
| 20 | - @param imageSize 图片大小 (逻辑像素) | ||
| 21 | - @param orientation 图片浏览器的方向 | ||
| 22 | - @return 图片展示的位置 (frame) | ||
| 23 | - */ | ||
| 24 | -- (CGRect)yb_imageViewFrameWithContainerSize:(CGSize)containerSize imageSize:(CGSize)imageSize orientation:(UIDeviceOrientation)orientation; | ||
| 25 | - | ||
| 26 | -/** | ||
| 27 | - 计算最大缩放比例 | ||
| 28 | - | ||
| 29 | - @param containerSize 容器大小 | ||
| 30 | - @param imageSize 图片大小 (逻辑像素) | ||
| 31 | - @param orientation 图片浏览器的方向 | ||
| 32 | - @return 最大缩放比例 | ||
| 33 | - */ | ||
| 34 | -- (CGFloat)yb_maximumZoomScaleWithContainerSize:(CGSize)containerSize imageSize:(CGSize)imageSize orientation:(UIDeviceOrientation)orientation; | ||
| 35 | - | ||
| 36 | -@end | ||
| 37 | - | ||
| 38 | -typedef NS_ENUM(NSUInteger, YBIBImageFillType) { | ||
| 39 | - /// 宽度优先填充满 | ||
| 40 | - YBIBImageFillTypeFullWidth, | ||
| 41 | - /// 完整显示 | ||
| 42 | - YBIBImageFillTypeCompletely | ||
| 43 | -}; | ||
| 44 | - | ||
| 45 | -@interface YBIBImageLayout : NSObject <YBIBImageLayout> | ||
| 46 | - | ||
| 47 | -/// 纵向的填充方式,默认 YBIBImageFillTypeCompletely | ||
| 48 | -@property (nonatomic, assign) YBIBImageFillType verticalFillType; | ||
| 49 | - | ||
| 50 | -/// 横向的填充方式,默认 YBIBImageFillTypeFullWidth | ||
| 51 | -@property (nonatomic, assign) YBIBImageFillType horizontalFillType; | ||
| 52 | - | ||
| 53 | -/// 最大缩放比例 (必须大于 1 才有效,若不指定内部会自动计算) | ||
| 54 | -@property (nonatomic, assign) CGFloat maxZoomScale; | ||
| 55 | - | ||
| 56 | -/// 自动计算严格缩放比例后,再乘以这个值作为最终缩放比例,默认 1.5 | ||
| 57 | -@property (nonatomic, assign) CGFloat zoomScaleSurplus; | ||
| 58 | - | ||
| 59 | -@end | ||
| 60 | - | ||
| 61 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Image/YBIBImageLayout.m deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBImageLayout.m | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/12. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBImageLayout.h" | ||
| 10 | - | ||
| 11 | -@implementation YBIBImageLayout | ||
| 12 | - | ||
| 13 | -#pragma mark - life cycle | ||
| 14 | - | ||
| 15 | -- (instancetype)init { | ||
| 16 | - self = [super init]; | ||
| 17 | - if (self) { | ||
| 18 | - _verticalFillType = YBIBImageFillTypeCompletely; | ||
| 19 | - _horizontalFillType = YBIBImageFillTypeFullWidth; | ||
| 20 | - _zoomScaleSurplus = 1.5; | ||
| 21 | - } | ||
| 22 | - return self; | ||
| 23 | -} | ||
| 24 | - | ||
| 25 | -#pragma mark - private | ||
| 26 | - | ||
| 27 | -- (YBIBImageFillType)fillTypeByOrientation:(UIDeviceOrientation)orientation { | ||
| 28 | - return UIDeviceOrientationIsLandscape(orientation) ? self.horizontalFillType : self.verticalFillType; | ||
| 29 | -} | ||
| 30 | - | ||
| 31 | -#pragma mark - <YBIBImageLayout> | ||
| 32 | - | ||
| 33 | -- (CGRect)yb_imageViewFrameWithContainerSize:(CGSize)containerSize imageSize:(CGSize)imageSize orientation:(UIDeviceOrientation)orientation { | ||
| 34 | - if (containerSize.width <= 0 || containerSize.height <= 0 || imageSize.width <= 0 || imageSize.height <= 0) return CGRectZero; | ||
| 35 | - | ||
| 36 | - CGFloat x = 0, y = 0, width = 0, height = 0; | ||
| 37 | - switch ([self fillTypeByOrientation:orientation]) { | ||
| 38 | - case YBIBImageFillTypeFullWidth: { | ||
| 39 | - x = 0; | ||
| 40 | - width = containerSize.width; | ||
| 41 | - height = containerSize.width * (imageSize.height / imageSize.width); | ||
| 42 | - if (imageSize.width / imageSize.height >= containerSize.width / containerSize.height) | ||
| 43 | - y = (containerSize.height - height) / 2.0; | ||
| 44 | - else | ||
| 45 | - y = 0; | ||
| 46 | - } | ||
| 47 | - break; | ||
| 48 | - case YBIBImageFillTypeCompletely: { | ||
| 49 | - if (imageSize.width / imageSize.height >= containerSize.width / containerSize.height) { | ||
| 50 | - width = containerSize.width; | ||
| 51 | - height = containerSize.width * (imageSize.height / imageSize.width); | ||
| 52 | - x = 0; | ||
| 53 | - y = (containerSize.height - height) / 2.0; | ||
| 54 | - } else { | ||
| 55 | - height = containerSize.height; | ||
| 56 | - width = containerSize.height * (imageSize.width / imageSize.height); | ||
| 57 | - x = (containerSize.width - width) / 2.0; | ||
| 58 | - y = 0; | ||
| 59 | - } | ||
| 60 | - } | ||
| 61 | - break; | ||
| 62 | - default: return CGRectZero; | ||
| 63 | - } | ||
| 64 | - return CGRectMake(x, y, width, height); | ||
| 65 | -} | ||
| 66 | - | ||
| 67 | -- (CGFloat)yb_maximumZoomScaleWithContainerSize:(CGSize)containerSize imageSize:(CGSize)imageSize orientation:(UIDeviceOrientation)orientation { | ||
| 68 | - if (self.maxZoomScale >= 1) return self.maxZoomScale; | ||
| 69 | - | ||
| 70 | - if (containerSize.width <= 0 || containerSize.height <= 0) return 0; | ||
| 71 | - | ||
| 72 | - CGFloat scale = [UIScreen mainScreen].scale; | ||
| 73 | - if (scale <= 0) return 0; | ||
| 74 | - | ||
| 75 | - CGFloat widthScale = imageSize.width / scale / containerSize.width, | ||
| 76 | - heightScale = imageSize.height / scale / containerSize.height, | ||
| 77 | - maxScale = 1; | ||
| 78 | - switch ([self fillTypeByOrientation:orientation]) { | ||
| 79 | - case YBIBImageFillTypeFullWidth: | ||
| 80 | - maxScale = widthScale; | ||
| 81 | - break; | ||
| 82 | - case YBIBImageFillTypeCompletely: | ||
| 83 | - maxScale = MAX(widthScale, heightScale); | ||
| 84 | - break; | ||
| 85 | - default: return 0; | ||
| 86 | - } | ||
| 87 | - return MAX(maxScale, 1) * self.zoomScaleSurplus; | ||
| 88 | -} | ||
| 89 | - | ||
| 90 | -@end |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Image/YBIBImageScrollView.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBImageScrollView.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/10. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBImage.h" | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | -typedef NS_ENUM(NSInteger, YBIBScrollImageType) { | ||
| 14 | - YBIBScrollImageTypeNone, | ||
| 15 | - YBIBScrollImageTypeOriginal, | ||
| 16 | - YBIBScrollImageTypeCompressed, | ||
| 17 | - YBIBScrollImageTypeThumb | ||
| 18 | -}; | ||
| 19 | - | ||
| 20 | -@interface YBIBImageScrollView : UIScrollView | ||
| 21 | - | ||
| 22 | -- (void)setImage:(__kindof UIImage *)image type:(YBIBScrollImageType)type; | ||
| 23 | - | ||
| 24 | -@property (nonatomic, strong, readonly) YYAnimatedImageView *imageView; | ||
| 25 | - | ||
| 26 | -@property (nonatomic, assign) YBIBScrollImageType imageType; | ||
| 27 | - | ||
| 28 | -- (void)reset; | ||
| 29 | - | ||
| 30 | -@end | ||
| 31 | - | ||
| 32 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Image/YBIBImageScrollView.m deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBImageScrollView.m | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/10. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBImageScrollView.h" | ||
| 10 | - | ||
| 11 | -@interface YBIBImageScrollView () | ||
| 12 | -@property (nonatomic, strong) YYAnimatedImageView *imageView; | ||
| 13 | -@end | ||
| 14 | - | ||
| 15 | -@implementation YBIBImageScrollView | ||
| 16 | - | ||
| 17 | -#pragma mark - life cycle | ||
| 18 | - | ||
| 19 | -- (instancetype)initWithFrame:(CGRect)frame { | ||
| 20 | - self = [super initWithFrame:frame]; | ||
| 21 | - if (self) { | ||
| 22 | - self.showsHorizontalScrollIndicator = NO; | ||
| 23 | - self.showsVerticalScrollIndicator = NO; | ||
| 24 | - self.decelerationRate = UIScrollViewDecelerationRateFast; | ||
| 25 | - self.maximumZoomScale = 1; | ||
| 26 | - self.minimumZoomScale = 1; | ||
| 27 | - self.alwaysBounceHorizontal = NO; | ||
| 28 | - self.alwaysBounceVertical = NO; | ||
| 29 | - self.layer.masksToBounds = NO; | ||
| 30 | - if (@available(iOS 11.0, *)) { | ||
| 31 | - self.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; | ||
| 32 | - } | ||
| 33 | - | ||
| 34 | - [self addSubview:self.imageView]; | ||
| 35 | - } | ||
| 36 | - return self; | ||
| 37 | -} | ||
| 38 | - | ||
| 39 | -#pragma mark - public | ||
| 40 | - | ||
| 41 | -- (void)setImage:(__kindof UIImage *)image type:(YBIBScrollImageType)type { | ||
| 42 | - self.imageView.image = image; | ||
| 43 | - self.imageType = type; | ||
| 44 | -} | ||
| 45 | - | ||
| 46 | -- (void)reset { | ||
| 47 | - self.zoomScale = 1; | ||
| 48 | - self.imageView.image = nil; | ||
| 49 | - self.imageView.frame = CGRectZero; | ||
| 50 | - self.imageType = YBIBScrollImageTypeNone; | ||
| 51 | -} | ||
| 52 | - | ||
| 53 | -#pragma mark - getters | ||
| 54 | - | ||
| 55 | -- (YYAnimatedImageView *)imageView { | ||
| 56 | - if (!_imageView) { | ||
| 57 | - _imageView = [YYAnimatedImageView new]; | ||
| 58 | - _imageView.contentMode = UIViewContentModeScaleAspectFill; | ||
| 59 | - _imageView.layer.masksToBounds = YES; | ||
| 60 | - } | ||
| 61 | - return _imageView; | ||
| 62 | -} | ||
| 63 | - | ||
| 64 | -@end |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Image/YBIBInteractionProfile.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBInteractionProfile.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/30. | ||
| 6 | -// Copyright © 2019 杨波. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import <UIKit/UIKit.h> | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | -@interface YBIBInteractionProfile : NSObject | ||
| 14 | - | ||
| 15 | -/// 是否取消手势交互动效 | ||
| 16 | -@property (nonatomic, assign) BOOL disable; | ||
| 17 | - | ||
| 18 | -/// 拖动的距离与最大高度的比例,达到这个比例就会出场 | ||
| 19 | -@property (nonatomic, assign) CGFloat dismissScale; | ||
| 20 | - | ||
| 21 | -/// 拖动的速度,达到这个值就会出场 | ||
| 22 | -@property (nonatomic, assign) CGFloat dismissVelocityY; | ||
| 23 | - | ||
| 24 | -/// 拖动动效复位时的时长 | ||
| 25 | -@property (nonatomic, assign) CGFloat restoreDuration; | ||
| 26 | - | ||
| 27 | -/// 拖动触发手势交互动效的起始距离 | ||
| 28 | -@property (nonatomic, assign) CGFloat triggerDistance; | ||
| 29 | - | ||
| 30 | -@end | ||
| 31 | - | ||
| 32 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Image/YBIBInteractionProfile.m deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBInteractionProfile.m | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/30. | ||
| 6 | -// Copyright © 2019 杨波. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBInteractionProfile.h" | ||
| 10 | - | ||
| 11 | -@implementation YBIBInteractionProfile | ||
| 12 | - | ||
| 13 | -- (instancetype)init { | ||
| 14 | - self = [super init]; | ||
| 15 | - if (self) { | ||
| 16 | - _disable = NO; | ||
| 17 | - _dismissScale = 0.22; | ||
| 18 | - _dismissVelocityY = 800; | ||
| 19 | - _restoreDuration = 0.15; | ||
| 20 | - _triggerDistance = 3; | ||
| 21 | - } | ||
| 22 | - return self; | ||
| 23 | -} | ||
| 24 | - | ||
| 25 | -@end |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Image/YBImage.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBImage.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2018/8/31. | ||
| 6 | -// Copyright © 2018年 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#if __has_include(<YYImage/YYImage.h>) | ||
| 10 | -#import <YYImage/YYFrameImage.h> | ||
| 11 | -#import <YYImage/YYSpriteSheetImage.h> | ||
| 12 | -#import <YYImage/YYImageCoder.h> | ||
| 13 | -#import <YYImage/YYAnimatedImageView.h> | ||
| 14 | -#elif __has_include(<YYWebImage/YYImage.h>) | ||
| 15 | -#import <YYWebImage/YYFrameImage.h> | ||
| 16 | -#import <YYWebImage/YYSpriteSheetImage.h> | ||
| 17 | -#import <YYWebImage/YYImageCoder.h> | ||
| 18 | -#import <YYWebImage/YYAnimatedImageView.h> | ||
| 19 | -#else | ||
| 20 | -#import "YYFrameImage.h" | ||
| 21 | -#import "YYSpriteSheetImage.h" | ||
| 22 | -#import "YYImageCoder.h" | ||
| 23 | -#import "YYAnimatedImageView.h" | ||
| 24 | -#endif | ||
| 25 | - | ||
| 26 | -NS_ASSUME_NONNULL_BEGIN | ||
| 27 | - | ||
| 28 | -/// 🙄波儿菜:Decide whether should to decode by image size. ('imageSize': physical pixel) | ||
| 29 | -typedef BOOL(^YBImageDecodeDecision)(CGSize imageSize, CGFloat scale); | ||
| 30 | - | ||
| 31 | -/** | ||
| 32 | - It is a fully compatible `UIImage` subclass. It extends the UIImage | ||
| 33 | - to support animated WebP, APNG and GIF format image data decoding. It also | ||
| 34 | - support NSCoding protocol to archive and unarchive multi-frame image data. | ||
| 35 | - | ||
| 36 | - If the image is created from multi-frame image data, and you want to play the | ||
| 37 | - animation, try replace UIImageView with `YYAnimatedImageView`. | ||
| 38 | - | ||
| 39 | - 🙄波儿菜:Copied from 'YYImage' and made some extensions. | ||
| 40 | - */ | ||
| 41 | - | ||
| 42 | -@interface YBImage : UIImage <YYAnimatedImage> | ||
| 43 | - | ||
| 44 | -+ (nullable __kindof UIImage *)imageNamed:(NSString *)name; // no cache! | ||
| 45 | -+ (nullable YBImage *)imageWithContentsOfFile:(NSString *)path; | ||
| 46 | -+ (nullable YBImage *)imageWithData:(NSData *)data; | ||
| 47 | -+ (nullable YBImage *)imageWithData:(NSData *)data scale:(CGFloat)scale; | ||
| 48 | - | ||
| 49 | -/// 🙄波儿菜:Expand methodes. | ||
| 50 | -/// Start -> | ||
| 51 | -+ (nullable __kindof UIImage *)imageNamed:(NSString *)name decodeDecision:(nullable YBImageDecodeDecision)decodeDecision; | ||
| 52 | -+ (nullable YBImage *)imageWithContentsOfFile:(NSString *)path decodeDecision:(nullable YBImageDecodeDecision)decodeDecision; | ||
| 53 | -+ (nullable YBImage *)imageWithData:(NSData *)data decodeDecision:(nullable YBImageDecodeDecision)decodeDecision; | ||
| 54 | -+ (nullable YBImage *)imageWithData:(NSData *)data scale:(CGFloat)scale decodeDecision:(nullable YBImageDecodeDecision)decodeDecision; | ||
| 55 | -/// <- End | ||
| 56 | - | ||
| 57 | -/** | ||
| 58 | - If the image is created from data or file, then the value indicates the data type. | ||
| 59 | - */ | ||
| 60 | -@property (nonatomic, readonly) YYImageType animatedImageType; | ||
| 61 | - | ||
| 62 | -/** | ||
| 63 | - If the image is created from animated image data (multi-frame GIF/APNG/WebP), | ||
| 64 | - this property stores the original image data. | ||
| 65 | - */ | ||
| 66 | -@property (nullable, nonatomic, readonly) NSData *animatedImageData; | ||
| 67 | - | ||
| 68 | -/** | ||
| 69 | - The total memory usage (in bytes) if all frame images was loaded into memory. | ||
| 70 | - The value is 0 if the image is not created from a multi-frame image data. | ||
| 71 | - */ | ||
| 72 | -@property (nonatomic, readonly) NSUInteger animatedImageMemorySize; | ||
| 73 | - | ||
| 74 | -/** | ||
| 75 | - Preload all frame image to memory. | ||
| 76 | - | ||
| 77 | - @discussion Set this property to `YES` will block the calling thread to decode | ||
| 78 | - all animation frame image to memory, set to `NO` will release the preloaded frames. | ||
| 79 | - If the image is shared by lots of image views (such as emoticon), preload all | ||
| 80 | - frames will reduce the CPU cost. | ||
| 81 | - | ||
| 82 | - See `animatedImageMemorySize` for memory cost. | ||
| 83 | - */ | ||
| 84 | -@property (nonatomic) BOOL preloadAllAnimatedImageFrames; | ||
| 85 | - | ||
| 86 | - | ||
| 87 | -@end | ||
| 88 | - | ||
| 89 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Image/YBImage.m deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBImage.m | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2018/8/31. | ||
| 6 | -// Copyright © 2018年 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBImage.h" | ||
| 10 | -#import "YBIBImageData.h" | ||
| 11 | -#import "YBIBUtilities.h" | ||
| 12 | - | ||
| 13 | -/** | ||
| 14 | - An array of NSNumber objects, shows the best order for path scale search. | ||
| 15 | - e.g. iPhone3GS:@[@1,@2,@3] iPhone5:@[@2,@3,@1] iPhone6 Plus:@[@3,@2,@1] | ||
| 16 | - */ | ||
| 17 | -static NSArray *_NSBundlePreferredScales() { | ||
| 18 | - static NSArray *scales; | ||
| 19 | - static dispatch_once_t onceToken; | ||
| 20 | - dispatch_once(&onceToken, ^{ | ||
| 21 | - CGFloat screenScale = [UIScreen mainScreen].scale; | ||
| 22 | - if (screenScale <= 1) { | ||
| 23 | - scales = @[@1,@2,@3]; | ||
| 24 | - } else if (screenScale <= 2) { | ||
| 25 | - scales = @[@2,@3,@1]; | ||
| 26 | - } else { | ||
| 27 | - scales = @[@3,@2,@1]; | ||
| 28 | - } | ||
| 29 | - }); | ||
| 30 | - return scales; | ||
| 31 | -} | ||
| 32 | - | ||
| 33 | -/** | ||
| 34 | - Add scale modifier to the file name (without path extension), | ||
| 35 | - From @"name" to @"name@2x". | ||
| 36 | - | ||
| 37 | - e.g. | ||
| 38 | - <table> | ||
| 39 | - <tr><th>Before </th><th>After(scale:2)</th></tr> | ||
| 40 | - <tr><td>"icon" </td><td>"icon@2x" </td></tr> | ||
| 41 | - <tr><td>"icon " </td><td>"icon @2x" </td></tr> | ||
| 42 | - <tr><td>"icon.top" </td><td>"icon.top@2x" </td></tr> | ||
| 43 | - <tr><td>"/p/name" </td><td>"/p/name@2x" </td></tr> | ||
| 44 | - <tr><td>"/path/" </td><td>"/path/" </td></tr> | ||
| 45 | - </table> | ||
| 46 | - | ||
| 47 | - @param scale Resource scale. | ||
| 48 | - @return String by add scale modifier, or just return if it's not end with file name. | ||
| 49 | - */ | ||
| 50 | -static NSString *_NSStringByAppendingNameScale(NSString *string, CGFloat scale) { | ||
| 51 | - if (!string) return nil; | ||
| 52 | - if (fabs(scale - 1) <= __FLT_EPSILON__ || string.length == 0 || [string hasSuffix:@"/"]) return string.copy; | ||
| 53 | - return [string stringByAppendingFormat:@"@%@x", @(scale)]; | ||
| 54 | -} | ||
| 55 | - | ||
| 56 | -/** | ||
| 57 | - Return the path scale. | ||
| 58 | - | ||
| 59 | - e.g. | ||
| 60 | - <table> | ||
| 61 | - <tr><th>Path </th><th>Scale </th></tr> | ||
| 62 | - <tr><td>"icon.png" </td><td>1 </td></tr> | ||
| 63 | - <tr><td>"icon@2x.png" </td><td>2 </td></tr> | ||
| 64 | - <tr><td>"icon@2.5x.png" </td><td>2.5 </td></tr> | ||
| 65 | - <tr><td>"icon@2x" </td><td>1 </td></tr> | ||
| 66 | - <tr><td>"icon@2x..png" </td><td>1 </td></tr> | ||
| 67 | - <tr><td>"icon@2x.png/" </td><td>1 </td></tr> | ||
| 68 | - </table> | ||
| 69 | - */ | ||
| 70 | -static CGFloat _NSStringPathScale(NSString *string) { | ||
| 71 | - if (string.length == 0 || [string hasSuffix:@"/"]) return 1; | ||
| 72 | - NSString *name = string.stringByDeletingPathExtension; | ||
| 73 | - __block CGFloat scale = 1; | ||
| 74 | - | ||
| 75 | - NSRegularExpression *pattern = [NSRegularExpression regularExpressionWithPattern:@"@[0-9]+\\.?[0-9]*x$" options:NSRegularExpressionAnchorsMatchLines error:nil]; | ||
| 76 | - [pattern enumerateMatchesInString:name options:kNilOptions range:NSMakeRange(0, name.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { | ||
| 77 | - if (result.range.location >= 3) { | ||
| 78 | - scale = [string substringWithRange:NSMakeRange(result.range.location + 1, result.range.length - 2)].doubleValue; | ||
| 79 | - } | ||
| 80 | - }]; | ||
| 81 | - | ||
| 82 | - return scale; | ||
| 83 | -} | ||
| 84 | - | ||
| 85 | - | ||
| 86 | -@implementation YBImage { | ||
| 87 | - YYImageDecoder *_decoder; | ||
| 88 | - NSArray *_preloadedFrames; | ||
| 89 | - dispatch_semaphore_t _preloadedLock; | ||
| 90 | - NSUInteger _bytesPerFrame; | ||
| 91 | -} | ||
| 92 | - | ||
| 93 | -+ (__kindof UIImage *)imageNamed:(NSString *)name { | ||
| 94 | - return [self imageNamed:name decodeDecision:nil]; | ||
| 95 | -} | ||
| 96 | -+ (__kindof UIImage *)imageNamed:(NSString *)name decodeDecision:(nullable YBImageDecodeDecision)decodeDecision { | ||
| 97 | - if (name.length == 0) return nil; | ||
| 98 | - if ([name hasSuffix:@"/"]) return nil; | ||
| 99 | - | ||
| 100 | - NSString *res = name.stringByDeletingPathExtension; | ||
| 101 | - NSString *ext = name.pathExtension; | ||
| 102 | - NSString *path = nil; | ||
| 103 | - CGFloat scale = 1; | ||
| 104 | - | ||
| 105 | - // If no extension, guess by system supported (same as UIImage). | ||
| 106 | - NSArray *exts = ext.length > 0 ? @[ext] : @[@"", @"png", @"jpeg", @"jpg", @"gif", @"webp", @"apng"]; | ||
| 107 | - NSArray *scales = _NSBundlePreferredScales(); | ||
| 108 | - for (int s = 0; s < scales.count; s++) { | ||
| 109 | - scale = ((NSNumber *)scales[s]).floatValue; | ||
| 110 | - NSString *scaledName = _NSStringByAppendingNameScale(res, scale); | ||
| 111 | - for (NSString *e in exts) { | ||
| 112 | - path = [[NSBundle mainBundle] pathForResource:scaledName ofType:e]; | ||
| 113 | - if (path) break; | ||
| 114 | - } | ||
| 115 | - if (path) break; | ||
| 116 | - } | ||
| 117 | - if (path.length == 0) { | ||
| 118 | - // 🙄波儿菜:Assets.xcassets supported. | ||
| 119 | - return [super imageNamed:name]; | ||
| 120 | - } | ||
| 121 | - | ||
| 122 | - NSData *data = [NSData dataWithContentsOfFile:path]; | ||
| 123 | - if (data.length == 0) return nil; | ||
| 124 | - | ||
| 125 | - return [[self alloc] initWithData:data scale:scale decodeDecision:decodeDecision]; | ||
| 126 | -} | ||
| 127 | - | ||
| 128 | -+ (YBImage *)imageWithContentsOfFile:(NSString *)path { | ||
| 129 | - return [self imageWithContentsOfFile:path decodeDecision:nil]; | ||
| 130 | -} | ||
| 131 | -+ (YBImage *)imageWithContentsOfFile:(NSString *)path decodeDecision:(nullable YBImageDecodeDecision)decodeDecision { | ||
| 132 | - return [[self alloc] initWithContentsOfFile:path decodeDecision:decodeDecision]; | ||
| 133 | -} | ||
| 134 | - | ||
| 135 | -+ (YBImage *)imageWithData:(NSData *)data { | ||
| 136 | - return [self imageWithData:data decodeDecision:nil]; | ||
| 137 | -} | ||
| 138 | -+ (YBImage *)imageWithData:(NSData *)data decodeDecision:(nullable YBImageDecodeDecision)decodeDecision { | ||
| 139 | - return [[self alloc] initWithData:data decodeDecision:decodeDecision]; | ||
| 140 | -} | ||
| 141 | - | ||
| 142 | -+ (YBImage *)imageWithData:(NSData *)data scale:(CGFloat)scale { | ||
| 143 | - return [self imageWithData:data scale:scale decodeDecision:nil]; | ||
| 144 | -} | ||
| 145 | -+ (YBImage *)imageWithData:(NSData *)data scale:(CGFloat)scale decodeDecision:(nullable YBImageDecodeDecision)decodeDecision { | ||
| 146 | - return [[self alloc] initWithData:data scale:scale decodeDecision:decodeDecision]; | ||
| 147 | -} | ||
| 148 | - | ||
| 149 | -- (instancetype)initWithContentsOfFile:(NSString *)path { | ||
| 150 | - return [self initWithContentsOfFile:path decodeDecision:nil]; | ||
| 151 | -} | ||
| 152 | -- (instancetype)initWithContentsOfFile:(NSString *)path decodeDecision:(nullable YBImageDecodeDecision)decodeDecision { | ||
| 153 | - NSData *data = [NSData dataWithContentsOfFile:path]; | ||
| 154 | - return [self initWithData:data scale:_NSStringPathScale(path) decodeDecision:decodeDecision]; | ||
| 155 | -} | ||
| 156 | - | ||
| 157 | -- (instancetype)initWithData:(NSData *)data { | ||
| 158 | - return [self initWithData:data decodeDecision:nil]; | ||
| 159 | -} | ||
| 160 | -- (instancetype)initWithData:(NSData *)data decodeDecision:(nullable YBImageDecodeDecision)decodeDecision { | ||
| 161 | - return [self initWithData:data scale:1 decodeDecision:decodeDecision]; | ||
| 162 | -} | ||
| 163 | - | ||
| 164 | -- (instancetype)initWithData:(NSData *)data scale:(CGFloat)scale { | ||
| 165 | - return [self initWithData:data scale:scale decodeDecision:nil]; | ||
| 166 | -} | ||
| 167 | -- (instancetype)initWithData:(NSData *)data scale:(CGFloat)scale decodeDecision:(nullable YBImageDecodeDecision)decodeDecision { | ||
| 168 | - if (data.length == 0) return nil; | ||
| 169 | - if (scale <= 0) scale = [UIScreen mainScreen].scale; | ||
| 170 | - _preloadedLock = dispatch_semaphore_create(1); | ||
| 171 | - @autoreleasepool { | ||
| 172 | - YYImageDecoder *decoder = [YYImageDecoder decoderWithData:data scale:scale]; | ||
| 173 | - | ||
| 174 | - // 🙄波儿菜:Determine whether should to decode. | ||
| 175 | - BOOL decodeForDisplay = YES; | ||
| 176 | - if (decodeDecision) { | ||
| 177 | - decodeForDisplay = decodeDecision(CGSizeMake(decoder.width, decoder.height), decoder.scale ?: 1); | ||
| 178 | - } | ||
| 179 | - | ||
| 180 | - YYImageFrame *frame = [decoder frameAtIndex:0 decodeForDisplay:decodeForDisplay]; | ||
| 181 | - UIImage *image = frame.image; | ||
| 182 | - if (!image) return nil; | ||
| 183 | - self = [self initWithCGImage:image.CGImage scale:decoder.scale orientation:image.imageOrientation]; | ||
| 184 | - if (!self) return nil; | ||
| 185 | - _animatedImageType = decoder.type; | ||
| 186 | - if (decoder.frameCount > 1) { | ||
| 187 | - _decoder = decoder; | ||
| 188 | - _bytesPerFrame = CGImageGetBytesPerRow(image.CGImage) * CGImageGetHeight(image.CGImage); | ||
| 189 | - _animatedImageMemorySize = _bytesPerFrame * decoder.frameCount; | ||
| 190 | - } | ||
| 191 | - self.yy_isDecodedForDisplay = YES; | ||
| 192 | - } | ||
| 193 | - return self; | ||
| 194 | -} | ||
| 195 | - | ||
| 196 | -- (NSData *)animatedImageData { | ||
| 197 | - return _decoder.data; | ||
| 198 | -} | ||
| 199 | - | ||
| 200 | -- (void)setPreloadAllAnimatedImageFrames:(BOOL)preloadAllAnimatedImageFrames { | ||
| 201 | - if (_preloadAllAnimatedImageFrames != preloadAllAnimatedImageFrames) { | ||
| 202 | - if (preloadAllAnimatedImageFrames && _decoder.frameCount > 0) { | ||
| 203 | - NSMutableArray *frames = [NSMutableArray new]; | ||
| 204 | - for (NSUInteger i = 0, max = _decoder.frameCount; i < max; i++) { | ||
| 205 | - UIImage *img = [self animatedImageFrameAtIndex:i]; | ||
| 206 | - if (img) { | ||
| 207 | - [frames addObject:img]; | ||
| 208 | - } else { | ||
| 209 | - [frames addObject:[NSNull null]]; | ||
| 210 | - } | ||
| 211 | - } | ||
| 212 | - dispatch_semaphore_wait(_preloadedLock, DISPATCH_TIME_FOREVER); | ||
| 213 | - _preloadedFrames = frames; | ||
| 214 | - dispatch_semaphore_signal(_preloadedLock); | ||
| 215 | - } else { | ||
| 216 | - dispatch_semaphore_wait(_preloadedLock, DISPATCH_TIME_FOREVER); | ||
| 217 | - _preloadedFrames = nil; | ||
| 218 | - dispatch_semaphore_signal(_preloadedLock); | ||
| 219 | - } | ||
| 220 | - } | ||
| 221 | -} | ||
| 222 | - | ||
| 223 | -#pragma mark - protocol NSCoding | ||
| 224 | - | ||
| 225 | -- (instancetype)initWithCoder:(NSCoder *)aDecoder { | ||
| 226 | - NSNumber *scale = [aDecoder decodeObjectForKey:@"YYImageScale"]; | ||
| 227 | - NSData *data = [aDecoder decodeObjectForKey:@"YYImageData"]; | ||
| 228 | - if (data.length) { | ||
| 229 | - self = [self initWithData:data scale:scale.doubleValue]; | ||
| 230 | - } else { | ||
| 231 | - self = [super initWithCoder:aDecoder]; | ||
| 232 | - } | ||
| 233 | - return self; | ||
| 234 | -} | ||
| 235 | - | ||
| 236 | -- (void)encodeWithCoder:(NSCoder *)aCoder { | ||
| 237 | - if (_decoder.data.length) { | ||
| 238 | - [aCoder encodeObject:@(self.scale) forKey:@"YYImageScale"]; | ||
| 239 | - [aCoder encodeObject:_decoder.data forKey:@"YYImageData"]; | ||
| 240 | - } else { | ||
| 241 | - [super encodeWithCoder:aCoder]; // Apple use UIImagePNGRepresentation() to encode UIImage. | ||
| 242 | - } | ||
| 243 | -} | ||
| 244 | - | ||
| 245 | -#pragma mark - protocol YYAnimatedImage | ||
| 246 | - | ||
| 247 | -- (NSUInteger)animatedImageFrameCount { | ||
| 248 | - return _decoder.frameCount; | ||
| 249 | -} | ||
| 250 | - | ||
| 251 | -- (NSUInteger)animatedImageLoopCount { | ||
| 252 | - return _decoder.loopCount; | ||
| 253 | -} | ||
| 254 | - | ||
| 255 | -- (NSUInteger)animatedImageBytesPerFrame { | ||
| 256 | - return _bytesPerFrame; | ||
| 257 | -} | ||
| 258 | - | ||
| 259 | -- (UIImage *)animatedImageFrameAtIndex:(NSUInteger)index { | ||
| 260 | - if (index >= _decoder.frameCount) return nil; | ||
| 261 | - dispatch_semaphore_wait(_preloadedLock, DISPATCH_TIME_FOREVER); | ||
| 262 | - UIImage *image = _preloadedFrames[index]; | ||
| 263 | - dispatch_semaphore_signal(_preloadedLock); | ||
| 264 | - if (image) return image == (id)[NSNull null] ? nil : image; | ||
| 265 | - return [_decoder frameAtIndex:index decodeForDisplay:YES].image; | ||
| 266 | -} | ||
| 267 | - | ||
| 268 | -- (NSTimeInterval)animatedImageDurationAtIndex:(NSUInteger)index { | ||
| 269 | - NSTimeInterval duration = [_decoder frameDurationAtIndex:index]; | ||
| 270 | - | ||
| 271 | - /* | ||
| 272 | - http://opensource.apple.com/source/WebCore/WebCore-7600.1.25/platform/graphics/cg/ImageSourceCG.cpp | ||
| 273 | - Many annoying ads specify a 0 duration to make an image flash as quickly as | ||
| 274 | - possible. We follow Safari and Firefox's behavior and use a duration of 100 ms | ||
| 275 | - for any frames that specify a duration of <= 10 ms. | ||
| 276 | - See <rdar://problem/7689300> and <http://webkit.org/b/36082> for more information. | ||
| 277 | - | ||
| 278 | - See also: http://nullsleep.tumblr.com/post/16524517190/animated-gif-minimum-frame-delay-browser. | ||
| 279 | - */ | ||
| 280 | - if (duration < 0.011f) return 0.100f; | ||
| 281 | - return duration; | ||
| 282 | -} | ||
| 283 | - | ||
| 284 | -@end |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Protocol/YBIBCellProtocol.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBCellProtocol.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/5. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBGetBaseInfoProtocol.h" | ||
| 10 | -#import "YBIBOrientationReceiveProtocol.h" | ||
| 11 | -#import "YBIBOperateBrowserProtocol.h" | ||
| 12 | - | ||
| 13 | -@protocol YBIBDataProtocol; | ||
| 14 | - | ||
| 15 | -NS_ASSUME_NONNULL_BEGIN | ||
| 16 | - | ||
| 17 | -@protocol YBIBCellProtocol <YBIBGetBaseInfoProtocol, YBIBOperateBrowserProtocol, YBIBOrientationReceiveProtocol> | ||
| 18 | - | ||
| 19 | -@required | ||
| 20 | - | ||
| 21 | -/// Cell 对应的 Data | ||
| 22 | -@property (nonatomic, strong) id<YBIBDataProtocol> yb_cellData; | ||
| 23 | - | ||
| 24 | -@optional | ||
| 25 | - | ||
| 26 | -/** | ||
| 27 | - 获取前景视图,出入场时需要用这个返回值做动效 | ||
| 28 | - | ||
| 29 | - @return 前景视图 | ||
| 30 | - */ | ||
| 31 | -- (__kindof UIView *)yb_foregroundView; | ||
| 32 | - | ||
| 33 | -/** | ||
| 34 | - 页码变化了 | ||
| 35 | - */ | ||
| 36 | -- (void)yb_pageChanged; | ||
| 37 | - | ||
| 38 | -/// 当前 Cell 的页码 | ||
| 39 | -@property (nonatomic, copy) NSInteger(^yb_selfPage)(void); | ||
| 40 | - | ||
| 41 | -@end | ||
| 42 | - | ||
| 43 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Protocol/YBIBDataProtocol.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBDataProtocol.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/5. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import "YBIBGetBaseInfoProtocol.h" | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | -@protocol YBIBDataProtocol <YBIBGetBaseInfoProtocol> | ||
| 14 | - | ||
| 15 | -@required | ||
| 16 | - | ||
| 17 | -/** | ||
| 18 | - 当前 Data 对应 Cell 的类类型 | ||
| 19 | - | ||
| 20 | - @return Class 类型 | ||
| 21 | - */ | ||
| 22 | -- (Class)yb_classOfCell; | ||
| 23 | - | ||
| 24 | -@optional | ||
| 25 | - | ||
| 26 | -/** | ||
| 27 | - 获取投影视图,当前数据模型对应外界业务的 UIView (通常为 UIImageView),做转场动效用 | ||
| 28 | - | ||
| 29 | - 这个方法会在做出入场动效时调用,若未实现时将无法进行平滑的入场 | ||
| 30 | - | ||
| 31 | - @return 投影视图 | ||
| 32 | - */ | ||
| 33 | -- (__kindof UIView *)yb_projectiveView; | ||
| 34 | - | ||
| 35 | -/** | ||
| 36 | - 通过一系列数据,计算并返回图片视图在容器中的 frame | ||
| 37 | - | ||
| 38 | - 这个方法会在做入场动效时调用,若未实现时将无法进行平滑的入场 | ||
| 39 | - | ||
| 40 | - @param containerSize 容器大小 | ||
| 41 | - @param imageSize 图片大小 (逻辑像素) | ||
| 42 | - @param orientation 图片浏览器的方向 | ||
| 43 | - @return 计算好的 frame | ||
| 44 | - */ | ||
| 45 | -- (CGRect)yb_imageViewFrameWithContainerSize:(CGSize)containerSize imageSize:(CGSize)imageSize orientation:(UIDeviceOrientation)orientation; | ||
| 46 | - | ||
| 47 | -/** | ||
| 48 | - 预加载数据,有效的预加载能提高性能,请注意管理内存 | ||
| 49 | - */ | ||
| 50 | -- (void)yb_preload; | ||
| 51 | - | ||
| 52 | -/** | ||
| 53 | - 保存到相册 | ||
| 54 | - */ | ||
| 55 | -- (void)yb_saveToPhotoAlbum; | ||
| 56 | - | ||
| 57 | -/** | ||
| 58 | - 是否允许保存到相册 | ||
| 59 | - */ | ||
| 60 | -- (BOOL)yb_allowSaveToPhotoAlbum; | ||
| 61 | - | ||
| 62 | -@end | ||
| 63 | - | ||
| 64 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Protocol/YBIBGetBaseInfoProtocol.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBGetBaseInfoProtocol.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/6/23. | ||
| 6 | -// Copyright © 2019 波儿菜. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import <UIKit/UIKit.h> | ||
| 10 | -#import "YBIBAuxiliaryViewHandler.h" | ||
| 11 | -#import "YBIBWebImageMediator.h" | ||
| 12 | - | ||
| 13 | -NS_ASSUME_NONNULL_BEGIN | ||
| 14 | - | ||
| 15 | -@protocol YBIBGetBaseInfoProtocol <NSObject> | ||
| 16 | - | ||
| 17 | -@optional | ||
| 18 | - | ||
| 19 | -/// 当前的方向 | ||
| 20 | -@property (nonatomic, copy) UIDeviceOrientation(^yb_currentOrientation)(void); | ||
| 21 | - | ||
| 22 | -/// 根据方向获取容器大小 | ||
| 23 | -@property (nonatomic, copy) CGSize(^yb_containerSize)(UIDeviceOrientation orientation); | ||
| 24 | - | ||
| 25 | -/// 容器视图 (可在上面添加子视图) | ||
| 26 | -@property (nonatomic, weak) UIView *yb_containerView; | ||
| 27 | - | ||
| 28 | -/// 辅助视图处理器 | ||
| 29 | -@property (nonatomic, copy) id<YBIBAuxiliaryViewHandler>(^yb_auxiliaryViewHandler)(void); | ||
| 30 | - | ||
| 31 | -/// 图片下载缓存相关中介者 | ||
| 32 | -@property (nonatomic, copy) id<YBIBWebImageMediator>(^yb_webImageMediator)(void); | ||
| 33 | - | ||
| 34 | -/// 当前页码 | ||
| 35 | -@property (nonatomic, copy) NSInteger(^yb_currentPage)(void); | ||
| 36 | - | ||
| 37 | -/// 总页码数量 | ||
| 38 | -@property (nonatomic, copy) NSInteger(^yb_totalPage)(void); | ||
| 39 | - | ||
| 40 | -/// 判断当前展示的 cell 是否恰好在屏幕中间 | ||
| 41 | -@property (nonatomic, copy) BOOL(^yb_cellIsInCenter)(void); | ||
| 42 | - | ||
| 43 | -/// 是否正在转场 | ||
| 44 | -@property (nonatomic, copy) BOOL(^yb_isTransitioning)(void); | ||
| 45 | -/// 是否正在展示过程转场 | ||
| 46 | -@property (nonatomic, copy) BOOL(^yb_isShowTransitioning)(void); | ||
| 47 | -/// 是否正在隐藏过程转场 | ||
| 48 | -@property (nonatomic, copy) BOOL(^yb_isHideTransitioning)(void); | ||
| 49 | - | ||
| 50 | -/// 是否正在旋转 | ||
| 51 | -@property (nonatomic, copy) BOOL(^yb_isRotating)(void); | ||
| 52 | - | ||
| 53 | -/// 背景视图 (也就是 YBImageBrower 对象,不可在上面添加子视图。作用:一是可以更改透明度和颜色,入场和出场动效有用;二是可以用来比较内存指针,在做不同实例差异化功能时可能有用,虽然不提倡这么做) | ||
| 54 | -@property (nonatomic, weak) __kindof UIView *yb_backView; | ||
| 55 | - | ||
| 56 | -/// 集合视图 | ||
| 57 | -@property (nonatomic, copy) __kindof UICollectionView *(^yb_collectionView)(void); | ||
| 58 | - | ||
| 59 | -@end | ||
| 60 | - | ||
| 61 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Protocol/YBIBOperateBrowserProtocol.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBOperateBrowserProtocol.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/7/8. | ||
| 6 | -// Copyright © 2019 杨波. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import <Foundation/Foundation.h> | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | -@protocol YBIBOperateBrowserProtocol <NSObject> | ||
| 14 | - | ||
| 15 | -@optional | ||
| 16 | - | ||
| 17 | -/// 隐藏图片浏览器 | ||
| 18 | -@property (nonatomic, copy) void(^yb_hideBrowser)(void); | ||
| 19 | - | ||
| 20 | -/// 是否隐藏状态栏 | ||
| 21 | -@property (nonatomic, copy) void(^yb_hideStatusBar)(BOOL); | ||
| 22 | - | ||
| 23 | -/// 是否隐藏工具视图 | ||
| 24 | -@property (nonatomic, copy) void(^yb_hideToolViews)(BOOL); | ||
| 25 | - | ||
| 26 | -@end | ||
| 27 | - | ||
| 28 | -NS_ASSUME_NONNULL_END |
CNLiveOrganizationValidationModule/Classes/CNLiveOrganizationValidationModule/YBImageBrowser/Protocol/YBIBOrientationReceiveProtocol.h deleted
100644 → 0
| 1 | -// | ||
| 2 | -// YBIBOrientationReceiveProtocol.h | ||
| 3 | -// YBImageBrowserDemo | ||
| 4 | -// | ||
| 5 | -// Created by 波儿菜 on 2019/7/8. | ||
| 6 | -// Copyright © 2019 杨波. All rights reserved. | ||
| 7 | -// | ||
| 8 | - | ||
| 9 | -#import <UIKit/UIKit.h> | ||
| 10 | - | ||
| 11 | -NS_ASSUME_NONNULL_BEGIN | ||
| 12 | - | ||
| 13 | -@protocol YBIBOrientationReceiveProtocol <NSObject> | ||
| 14 | - | ||
| 15 | -@optional | ||
| 16 | - | ||
| 17 | -/** | ||
| 18 | - 图片浏览器的方向将要变化 | ||
| 19 | - | ||
| 20 | - @param orientation 期望的方向 | ||
| 21 | - */ | ||
| 22 | -- (void)yb_orientationWillChangeWithExpectOrientation:(UIDeviceOrientation)orientation; | ||
| 23 | - | ||
| 24 | -/** | ||
| 25 | - 图片浏览器的方向变化动效调用,实现的变化会自动转换为动画 | ||
| 26 | - | ||
| 27 | - @param orientation 期望的方向 | ||
| 28 | - */ | ||
| 29 | -- (void)yb_orientationChangeAnimationWithExpectOrientation:(UIDeviceOrientation)orientation; | ||
| 30 | - | ||
| 31 | -/** | ||
| 32 | - 图片浏览器的方向已经变化 | ||
| 33 | - | ||
| 34 | - @param orientation 当前的方向 | ||
| 35 | - */ | ||
| 36 | -- (void)yb_orientationDidChangedWithOrientation:(UIDeviceOrientation)orientation; | ||
| 37 | - | ||
| 38 | -@end | ||
| 39 | - | ||
| 40 | -NS_ASSUME_NONNULL_END |