Commit 37b14d5c authored by Syan's avatar Syan

v0.1.8

parent 0a974a18
......@@ -12,7 +12,7 @@
### 原生框架依赖
* Android: [PictureSelector 2.2.3](https://github.com/LuckSiege/PictureSelector) - by [LuckSiege](https://github.com/LuckSiege)
* iOS:[TZImagePickerController 2.1.8](https://github.com/banchichen/TZImagePickerController) - by [banchichen](https://github.com/banchichen)
* iOS:[TZImagePickerController 3.0.9](https://github.com/banchichen/TZImagePickerController) - by [banchichen](https://github.com/banchichen)
### 功能特点
* 支持 iOS、Android 两端
......
......@@ -23,6 +23,7 @@ const defaultOptions = {
showCropGrid: false, // 是否隐藏裁剪区域网格,默认false
quality: 90, // 压缩质量
enableBase64: false, // 是否返回base64编码,默认不返回
allowPickingOriginalPhoto: false
};
export default {
......
......@@ -98,6 +98,7 @@ RCT_EXPORT_METHOD(removeAllPhoto) {
BOOL isGif = [self.cameraOptions sy_boolForKey:@"isGif"];
BOOL showCropCircle = [self.cameraOptions sy_boolForKey:@"showCropCircle"];
BOOL isRecordSelected = [self.cameraOptions sy_boolForKey:@"isRecordSelected"];
BOOL allowPickingOriginalPhoto = [self.cameraOptions sy_boolForKey:@"allowPickingOriginalPhoto"];
NSInteger CropW = [self.cameraOptions sy_integerForKey:@"CropW"];
NSInteger CropH = [self.cameraOptions sy_integerForKey:@"CropH"];
NSInteger circleCropRadius = [self.cameraOptions sy_integerForKey:@"circleCropRadius"];
......@@ -109,27 +110,22 @@ RCT_EXPORT_METHOD(removeAllPhoto) {
imagePickerVc.allowPickingGif = isGif; // 允许GIF
imagePickerVc.allowTakePicture = isCamera; // 允许用户在内部拍照
imagePickerVc.allowPickingVideo = NO; // 不允许视频
imagePickerVc.allowPickingOriginalPhoto = NO; // 允许原图
imagePickerVc.allowPickingOriginalPhoto = allowPickingOriginalPhoto; // 允许原图
imagePickerVc.alwaysEnableDoneBtn = YES;
imagePickerVc.allowCrop = isCrop; // 裁剪
if (isRecordSelected) {
imagePickerVc.selectedAssets = self.selectedAssets; // 当前已选中的图片
}
if (imageCount == 1) {
// 单选模式
imagePickerVc.showSelectBtn = NO;
imagePickerVc.allowPreview = NO;
if(isCrop){
if(showCropCircle) {
imagePickerVc.needCircleCrop = showCropCircle; //圆形裁剪
imagePickerVc.circleCropRadius = circleCropRadius; //圆形半径
imagePickerVc.circleCropRadius = circleCropRadius / 2; //圆形半径
} else {
CGFloat x = ([[UIScreen mainScreen] bounds].size.width - CropW) / 2;
CGFloat y = ([[UIScreen mainScreen] bounds].size.height - CropH) / 2;
imagePickerVc.cropRect = imagePickerVc.cropRect = CGRectMake(x,y,CropW,CropH);
imagePickerVc.cropRect = CGRectMake(x,y,CropW,CropH);
}
}
}
......@@ -172,38 +168,24 @@ RCT_EXPORT_METHOD(removeAllPhoto) {
#pragma mark - UIImagePickerController
- (void)takePhoto {
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if ((authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied) && iOS7Later) {
if (authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied) {
// 无相机权限 做一个友好的提示
if (iOS8Later) {
UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"无法使用相机" message:@"请在iPhone的""设置-隐私-相机""中允许访问相机" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"设置", nil];
[alert show];
} else {
UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"无法使用相机" message:@"请在iPhone的""设置-隐私-相机""中允许访问相机" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil];
[alert show];
}
} else if (authStatus == AVAuthorizationStatusNotDetermined) {
// fix issue 466, 防止用户首次拍照拒绝授权时相机页黑屏
if (iOS7Later) {
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
if (granted) {
dispatch_sync(dispatch_get_main_queue(), ^{
dispatch_async(dispatch_get_main_queue(), ^{
[self takePhoto];
});
}
}];
} else {
[self takePhoto];
}
// 拍照之前还需要检查相册权限
} else if ([TZImageManager authorizationStatus] == 2) { // 已被拒绝,没有相册权限,将无法保存拍的照片
if (iOS8Later) {
} else if ([PHPhotoLibrary authorizationStatus] == 2) { // 已被拒绝,没有相册权限,将无法保存拍的照片
UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"无法访问相册" message:@"请在iPhone的""设置-隐私-相册""中允许访问相册" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"设置", nil];
[alert show];
} else {
UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"无法访问相册" message:@"请在iPhone的""设置-隐私-相册""中允许访问相册" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil];
[alert show];
}
} else if ([TZImageManager authorizationStatus] == 0) { // 未请求过相册权限
} else if ([PHPhotoLibrary authorizationStatus] == 0) { // 未请求过相册权限
[[TZImageManager manager] requestAuthorizationWithCompletion:^{
[self takePhoto];
}];
......@@ -217,9 +199,6 @@ RCT_EXPORT_METHOD(removeAllPhoto) {
UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypeCamera;
if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]) {
self.imagePickerVc.sourceType = sourceType;
if(iOS8Later) {
self.imagePickerVc.modalPresentationStyle = UIModalPresentationOverCurrentContext;
}
[[self topViewController] presentViewController:self.imagePickerVc animated:YES completion:nil];
} else {
NSLog(@"模拟器中无法打开照相机,请在真机中使用");
......@@ -237,7 +216,7 @@ RCT_EXPORT_METHOD(removeAllPhoto) {
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
// save photo and get asset / 保存图片,获取到asset
[[TZImageManager manager] savePhotoWithImage:image location:NULL completion:^(NSError *error){
[[TZImageManager manager] savePhotoWithImage:image location:NULL completion:^(PHAsset *asset, NSError *error){
if (error) {
[tzImagePickerVc hideProgressHUD];
NSLog(@"图片保存失败 %@",error);
......@@ -289,10 +268,8 @@ RCT_EXPORT_METHOD(removeAllPhoto) {
#pragma mark - UIAlertViewDelegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 1) { // 去设置界面,开启相机访问权限
if (iOS8Later) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}
}
}
- (NSDictionary *)handleImageData:(UIImage *) image quality:(NSInteger)quality {
......
......@@ -30,22 +30,14 @@
- (void)setModel:(TZAssetModel *)model {
_model = model;
if (iOS8Later) {
self.representedAssetIdentifier = [[TZImageManager manager] getAssetIdentifier:model.asset];
}
self.representedAssetIdentifier = model.asset.localIdentifier;
if (self.useCachedImage && model.cachedImage) {
self.imageView.image = model.cachedImage;
} else {
self.model.cachedImage = nil;
int32_t imageRequestID = [[TZImageManager manager] getPhotoWithAsset:model.asset photoWidth:self.tz_width completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) {
// Set the cell's thumbnail image if it's still showing the same asset.
if (!iOS8Later) {
self.imageView.image = photo;
self.model.cachedImage = photo;
[self hideProgressView];
return;
}
if ([self.representedAssetIdentifier isEqualToString:[[TZImageManager manager] getAssetIdentifier:model.asset]]) {
if ([self.representedAssetIdentifier isEqualToString:model.asset.localIdentifier]) {
self.imageView.image = photo;
self.model.cachedImage = photo;
} else {
......@@ -383,10 +375,9 @@
}
}
/// For fitting iOS6
- (void)layoutSubviews {
if (iOS7Later) [super layoutSubviews];
_selectedCountButton.frame = CGRectMake(self.tz_width - 24 - 30, 23, 24, 24);
[super layoutSubviews];
_selectedCountButton.frame = CGRectMake(self.contentView.tz_width - 24, 23, 24, 24);
NSInteger titleHeight = ceil(self.titleLabel.font.lineHeight);
self.titleLabel.frame = CGRectMake(80, (self.tz_height - titleHeight) / 2, self.tz_width - 80 - 50, titleHeight);
self.posterImageView.frame = CGRectMake(0, 0, 70, 70);
......@@ -397,7 +388,7 @@
}
- (void)layoutSublayersOfLayer:(CALayer *)layer {
if (iOS7Later) [super layoutSublayersOfLayer:layer];
[super layoutSublayersOfLayer:layer];
}
#pragma mark - Lazy load
......
......@@ -20,17 +20,17 @@ typedef enum : NSUInteger {
@class PHAsset;
@interface TZAssetModel : NSObject
@property (nonatomic, strong) id asset; ///< PHAsset or ALAsset
@property (nonatomic, strong) PHAsset *asset;
@property (nonatomic, assign) BOOL isSelected; ///< The select status of a photo, default is No
@property (nonatomic, assign) TZAssetModelMediaType type;
@property (assign, nonatomic) BOOL needOscillatoryAnimation;
@property (nonatomic, copy) NSString *timeLength;
@property (strong, nonatomic) UIImage *cachedImage;
/// Init a photo dataModel With a asset
/// 用一个PHAsset/ALAsset实例,初始化一个照片模型
+ (instancetype)modelWithAsset:(id)asset type:(TZAssetModelMediaType)type;
+ (instancetype)modelWithAsset:(id)asset type:(TZAssetModelMediaType)type timeLength:(NSString *)timeLength;
/// Init a photo dataModel With a PHAsset
/// 用一个PHAsset实例,初始化一个照片模型
+ (instancetype)modelWithAsset:(PHAsset *)asset type:(TZAssetModelMediaType)type;
+ (instancetype)modelWithAsset:(PHAsset *)asset type:(TZAssetModelMediaType)type timeLength:(NSString *)timeLength;
@end
......@@ -40,7 +40,7 @@ typedef enum : NSUInteger {
@property (nonatomic, strong) NSString *name; ///< The album name
@property (nonatomic, assign) NSInteger count; ///< Count of photos the album contain
@property (nonatomic, strong) id result; ///< PHFetchResult<PHAsset> or ALAssetsGroup<ALAsset>
@property (nonatomic, strong) PHFetchResult *result;
@property (nonatomic, strong) NSArray *models;
@property (nonatomic, strong) NSArray *selectedModels;
......@@ -48,6 +48,6 @@ typedef enum : NSUInteger {
@property (nonatomic, assign) BOOL isCameraRoll;
- (void)setResult:(id)result needFetchAssets:(BOOL)needFetchAssets;
- (void)setResult:(PHFetchResult *)result needFetchAssets:(BOOL)needFetchAssets;
@end
......@@ -11,7 +11,7 @@
@implementation TZAssetModel
+ (instancetype)modelWithAsset:(id)asset type:(TZAssetModelMediaType)type{
+ (instancetype)modelWithAsset:(PHAsset *)asset type:(TZAssetModelMediaType)type{
TZAssetModel *model = [[TZAssetModel alloc] init];
model.asset = asset;
model.isSelected = NO;
......@@ -19,7 +19,7 @@
return model;
}
+ (instancetype)modelWithAsset:(id)asset type:(TZAssetModelMediaType)type timeLength:(NSString *)timeLength {
+ (instancetype)modelWithAsset:(PHAsset *)asset type:(TZAssetModelMediaType)type timeLength:(NSString *)timeLength {
TZAssetModel *model = [self modelWithAsset:asset type:type];
model.timeLength = timeLength;
return model;
......@@ -31,7 +31,7 @@
@implementation TZAlbumModel
- (void)setResult:(id)result needFetchAssets:(BOOL)needFetchAssets {
- (void)setResult:(PHFetchResult *)result needFetchAssets:(BOOL)needFetchAssets {
_result = result;
if (needFetchAssets) {
[[TZImageManager manager] getAssetsFromFetchResult:result completion:^(NSArray<TZAssetModel *> *models) {
......@@ -57,7 +57,7 @@
[selectedAssets addObject:model.asset];
}
for (TZAssetModel *model in _models) {
if ([[TZImageManager manager] isAssetsArray:selectedAssets containAsset:model.asset]) {
if ([selectedAssets containsObject:model.asset]) {
self.selectedCount ++;
}
}
......
......@@ -43,7 +43,7 @@
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
_originStatusBarStyle = [UIApplication sharedApplication].statusBarStyle;
[UIApplication sharedApplication].statusBarStyle = iOS7Later ? UIStatusBarStyleLightContent : UIStatusBarStyleBlackOpaque;
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
}
- (void)viewWillDisappear:(BOOL)animated {
......@@ -96,6 +96,14 @@
}
}
- (UIStatusBarStyle)preferredStatusBarStyle {
TZImagePickerController *tzImagePicker = (TZImagePickerController *)self.navigationController;
if (tzImagePicker && [tzImagePicker isKindOfClass:[TZImagePickerController class]]) {
return tzImagePicker.statusBarStyle;
}
return [super preferredStatusBarStyle];
}
#pragma mark - Layout
- (void)viewDidLayoutSubviews {
......@@ -119,13 +127,11 @@
_toolBar.hidden = !_toolBar.isHidden;
[self.navigationController setNavigationBarHidden:_toolBar.isHidden];
TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
if (iOS7Later) {
if (_toolBar.isHidden) {
[UIApplication sharedApplication].statusBarHidden = YES;
} else if (tzImagePickerVc.needShowStatusBar) {
[UIApplication sharedApplication].statusBarHidden = NO;
}
}
}
- (void)doneButtonClick {
......
......@@ -133,7 +133,7 @@
}
else {
// images数组过大时内存会飙升,在这里限制下最大count
NSInteger maxCount = [TZImagePickerConfig sharedInstance].gifPreviewMaxImagesCount ?: 200;
NSInteger maxCount = [TZImagePickerConfig sharedInstance].gifPreviewMaxImagesCount ?: 50;
NSInteger interval = MAX((count + maxCount / 2) / maxCount, 1);
NSMutableArray *images = [NSMutableArray array];
......
......@@ -46,7 +46,6 @@
/// Return YES if Authorized 返回YES如果得到了授权
- (BOOL)authorizationStatusAuthorized;
+ (NSInteger)authorizationStatus;
- (void)requestAuthorizationWithCompletion:(void (^)(void))completion;
/// Get Album 获得相册/相册数组
......@@ -54,68 +53,68 @@
- (void)getAllAlbums:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage needFetchAssets:(BOOL)needFetchAssets completion:(void (^)(NSArray<TZAlbumModel *> *models))completion;
/// Get Assets 获得Asset数组
- (void)getAssetsFromFetchResult:(id)result completion:(void (^)(NSArray<TZAssetModel *> *models))completion;
- (void)getAssetsFromFetchResult:(id)result allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(NSArray<TZAssetModel *> *models))completion;
- (void)getAssetFromFetchResult:(id)result atIndex:(NSInteger)index allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(TZAssetModel *model))completion;
- (void)getAssetsFromFetchResult:(PHFetchResult *)result completion:(void (^)(NSArray<TZAssetModel *> *models))completion;
- (void)getAssetsFromFetchResult:(PHFetchResult *)result allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(NSArray<TZAssetModel *> *models))completion;
- (void)getAssetFromFetchResult:(PHFetchResult *)result atIndex:(NSInteger)index allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(TZAssetModel *model))completion;
/// Get photo 获得照片
- (void)getPostImageWithAlbumModel:(TZAlbumModel *)model completion:(void (^)(UIImage *postImage))completion;
- (int32_t)getPhotoWithAsset:(id)asset completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion;
- (int32_t)getPhotoWithAsset:(id)asset photoWidth:(CGFloat)photoWidth completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion;
- (int32_t)getPhotoWithAsset:(id)asset completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler networkAccessAllowed:(BOOL)networkAccessAllowed;
- (int32_t)getPhotoWithAsset:(id)asset photoWidth:(CGFloat)photoWidth completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler networkAccessAllowed:(BOOL)networkAccessAllowed;
- (int32_t)requestImageDataForAsset:(id)asset completion:(void (^)(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler;
- (int32_t)getPhotoWithAsset:(PHAsset *)asset completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion;
- (int32_t)getPhotoWithAsset:(PHAsset *)asset photoWidth:(CGFloat)photoWidth completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion;
- (int32_t)getPhotoWithAsset:(PHAsset *)asset completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler networkAccessAllowed:(BOOL)networkAccessAllowed;
- (int32_t)getPhotoWithAsset:(PHAsset *)asset photoWidth:(CGFloat)photoWidth completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler networkAccessAllowed:(BOOL)networkAccessAllowed;
- (int32_t)requestImageDataForAsset:(PHAsset *)asset completion:(void (^)(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler;
/// Get full Image 获取原图
/// 如下两个方法completion一般会调多次,一般会先返回缩略图,再返回原图(详见方法内部使用的系统API的说明),如果info[PHImageResultIsDegradedKey] 为 YES,则表明当前返回的是缩略图,否则是原图。
- (void)getOriginalPhotoWithAsset:(id)asset completion:(void (^)(UIImage *photo,NSDictionary *info))completion;
- (void)getOriginalPhotoWithAsset:(id)asset newCompletion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion;
- (void)getOriginalPhotoWithAsset:(PHAsset *)asset completion:(void (^)(UIImage *photo,NSDictionary *info))completion;
- (void)getOriginalPhotoWithAsset:(PHAsset *)asset newCompletion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion;
// 该方法中,completion只会走一次
- (void)getOriginalPhotoDataWithAsset:(id)asset completion:(void (^)(NSData *data,NSDictionary *info,BOOL isDegraded))completion;
- (void)getOriginalPhotoDataWithAsset:(id)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(NSData *data,NSDictionary *info,BOOL isDegraded))completion;
- (void)getOriginalPhotoDataWithAsset:(PHAsset *)asset completion:(void (^)(NSData *data,NSDictionary *info,BOOL isDegraded))completion;
- (void)getOriginalPhotoDataWithAsset:(PHAsset *)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(NSData *data,NSDictionary *info,BOOL isDegraded))completion;
/// Save photo 保存照片
- (void)savePhotoWithImage:(UIImage *)image completion:(void (^)(NSError *error))completion;
- (void)savePhotoWithImage:(UIImage *)image location:(CLLocation *)location completion:(void (^)(NSError *error))completion;
- (void)savePhotoWithImage:(UIImage *)image completion:(void (^)(PHAsset *asset, NSError *error))completion;
- (void)savePhotoWithImage:(UIImage *)image location:(CLLocation *)location completion:(void (^)(PHAsset *asset, NSError *error))completion;
/// Save video 保存视频
- (void)saveVideoWithUrl:(NSURL *)url completion:(void (^)(NSError *error))completion;
- (void)saveVideoWithUrl:(NSURL *)url location:(CLLocation *)location completion:(void (^)(NSError *error))completion;
- (void)saveVideoWithUrl:(NSURL *)url completion:(void (^)(PHAsset *asset, NSError *error))completion;
- (void)saveVideoWithUrl:(NSURL *)url location:(CLLocation *)location completion:(void (^)(PHAsset *asset, NSError *error))completion;
/// Get video 获得视频
- (void)getVideoWithAsset:(id)asset completion:(void (^)(AVPlayerItem * playerItem, NSDictionary * info))completion;
- (void)getVideoWithAsset:(id)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(AVPlayerItem *, NSDictionary *))completion;
- (void)getVideoWithAsset:(PHAsset *)asset completion:(void (^)(AVPlayerItem * playerItem, NSDictionary * info))completion;
- (void)getVideoWithAsset:(PHAsset *)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(AVPlayerItem *, NSDictionary *))completion;
/// Export video 导出视频 presetName: 预设名字,默认值是AVAssetExportPreset640x480
- (void)getVideoOutputPathWithAsset:(id)asset success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure;
- (void)getVideoOutputPathWithAsset:(id)asset presetName:(NSString *)presetName success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure;
- (void)getVideoOutputPathWithAsset:(PHAsset *)asset success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure;
- (void)getVideoOutputPathWithAsset:(PHAsset *)asset presetName:(NSString *)presetName success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure;
/// Deprecated, Use -getVideoOutputPathWithAsset:failure:success:
- (void)getVideoOutputPathWithAsset:(id)asset completion:(void (^)(NSString *outputPath))completion __attribute__((deprecated("Use -getVideoOutputPathWithAsset:failure:success:")));
- (void)getVideoOutputPathWithAsset:(PHAsset *)asset completion:(void (^)(NSString *outputPath))completion __attribute__((deprecated("Use -getVideoOutputPathWithAsset:failure:success:")));
/// Get photo bytes 获得一组照片的大小
- (void)getPhotosBytesWithArray:(NSArray *)photos completion:(void (^)(NSString *totalBytes))completion;
/// Judge is a assets array contain the asset 判断一个assets数组是否包含这个asset
- (BOOL)isAssetsArray:(NSArray *)assets containAsset:(id)asset;
- (NSString *)getAssetIdentifier:(id)asset;
- (BOOL)isCameraRollAlbum:(id)metadata;
- (BOOL)isCameraRollAlbum:(PHAssetCollection *)metadata;
/// 检查照片大小是否满足最小要求
- (BOOL)isPhotoSelectableWithAsset:(id)asset;
- (CGSize)photoSizeWithAsset:(id)asset;
- (BOOL)isPhotoSelectableWithAsset:(PHAsset *)asset;
/// 修正图片转向
- (UIImage *)fixOrientation:(UIImage *)aImage;
/// 获取asset的资源类型
- (TZAssetModelMediaType)getAssetType:(id)asset;
- (TZAssetModelMediaType)getAssetType:(PHAsset *)asset;
/// 缩放图片至新尺寸
- (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)size;
/// 判断asset是否是视频
- (BOOL)isVideo:(id)asset;
- (BOOL)isVideo:(PHAsset *)asset;
/// for TZImagePreviewController
- (NSString *)getNewTimeFromDurationSecond:(NSInteger)duration;
- (TZAssetModel *)createModelWithAsset:(PHAsset *)asset;
@end
......
......@@ -7,14 +7,12 @@
//
#import "TZImageManager.h"
#import <AssetsLibrary/AssetsLibrary.h>
#import "TZAssetModel.h"
#import "TZImagePickerController.h"
@interface TZImageManager ()
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
@property (nonatomic, strong) ALAssetsLibrary *assetLibrary;
@end
@implementation TZImageManager
......@@ -29,10 +27,8 @@ static dispatch_once_t onceToken;
+ (instancetype)manager {
dispatch_once(&onceToken, ^{
manager = [[self alloc] init];
if (iOS8Later) {
// manager.cachingImageManager = [[PHCachingImageManager alloc] init];
// manager.cachingImageManager.allowsCachingHighQualityImages = YES;
}
[manager configTZScreenWidth];
});
......@@ -67,14 +63,9 @@ static dispatch_once_t onceToken;
}
}
- (ALAssetsLibrary *)assetLibrary {
if (_assetLibrary == nil) _assetLibrary = [[ALAssetsLibrary alloc] init];
return _assetLibrary;
}
/// Return YES if Authorized 返回YES如果得到了授权
- (BOOL)authorizationStatusAuthorized {
NSInteger status = [self.class authorizationStatus];
NSInteger status = [PHPhotoLibrary authorizationStatus];
if (status == 0) {
/**
* 当某些情况下AuthorizationStatus == AuthorizationStatusNotDetermined时,无法弹出系统首次使用的授权alertView,系统应用设置里亦没有相册的设置,此时将无法使用,故作以下操作,弹出系统首次使用的授权alertView
......@@ -85,15 +76,6 @@ static dispatch_once_t onceToken;
return status == 3;
}
+ (NSInteger)authorizationStatus {
if (iOS8Later) {
return [PHPhotoLibrary authorizationStatus];
} else {
return [ALAssetsLibrary authorizationStatus];
}
return NO;
}
- (void)requestAuthorizationWithCompletion:(void (^)(void))completion {
void (^callCompletionBlock)(void) = ^(){
dispatch_async(dispatch_get_main_queue(), ^{
......@@ -103,19 +85,11 @@ static dispatch_once_t onceToken;
});
};
if (iOS8Later) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
callCompletionBlock();
}];
});
} else {
[self.assetLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
callCompletionBlock();
} failureBlock:^(NSError *error) {
callCompletionBlock();
}];
}
}
#pragma mark - Get Album
......@@ -123,7 +97,6 @@ static dispatch_once_t onceToken;
/// Get Album 获得相册/相册数组
- (void)getCameraRollAlbum:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage needFetchAssets:(BOOL)needFetchAssets completion:(void (^)(TZAlbumModel *model))completion {
__block TZAlbumModel *model;
if (iOS8Later) {
PHFetchOptions *option = [[PHFetchOptions alloc] init];
if (!allowPickingVideo) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld", PHAssetMediaTypeImage];
if (!allowPickingImage) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld",
......@@ -145,22 +118,10 @@ static dispatch_once_t onceToken;
break;
}
}
} else {
[self.assetLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
if ([group numberOfAssets] < 1) return;
if ([self isCameraRollAlbum:group]) {
NSString *name = [group valueForProperty:ALAssetsGroupPropertyName];
model = [self modelWithResult:group name:name isCameraRoll:YES needFetchAssets:needFetchAssets];
if (completion) completion(model);
*stop = YES;
}
} failureBlock:nil];
}
}
- (void)getAllAlbums:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage needFetchAssets:(BOOL)needFetchAssets completion:(void (^)(NSArray<TZAlbumModel *> *))completion{
NSMutableArray *albumArr = [NSMutableArray array];
if (iOS8Later) {
PHFetchOptions *option = [[PHFetchOptions alloc] init];
if (!allowPickingVideo) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld", PHAssetMediaTypeImage];
if (!allowPickingImage) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld",
......@@ -201,92 +162,33 @@ static dispatch_once_t onceToken;
}
}
if (completion && albumArr.count > 0) completion(albumArr);
} else {
[self.assetLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
if (group == nil) {
if (completion && albumArr.count > 0) completion(albumArr);
}
if ([group numberOfAssets] < 1) return;
NSString *name = [group valueForProperty:ALAssetsGroupPropertyName];
if ([self.pickerDelegate respondsToSelector:@selector(isAlbumCanSelect:result:)]) {
if (![self.pickerDelegate isAlbumCanSelect:name result:group]) {
return;
}
}
if ([self isCameraRollAlbum:group]) {
[albumArr insertObject:[self modelWithResult:group name:name isCameraRoll:YES needFetchAssets:needFetchAssets] atIndex:0];
} else if ([[group valueForProperty:ALAssetsGroupPropertyType] intValue] == ALAssetsGroupPhotoStream) {
if (albumArr.count) {
[albumArr insertObject:[self modelWithResult:group name:name isCameraRoll:NO needFetchAssets:needFetchAssets] atIndex:1];
} else {
[albumArr addObject:[self modelWithResult:group name:name isCameraRoll:NO needFetchAssets:needFetchAssets]];
}
} else {
[albumArr addObject:[self modelWithResult:group name:name isCameraRoll:NO needFetchAssets:needFetchAssets]];
}
} failureBlock:nil];
}
}
#pragma mark - Get Assets
/// Get Assets 获得照片数组
- (void)getAssetsFromFetchResult:(id)result completion:(void (^)(NSArray<TZAssetModel *> *))completion {
- (void)getAssetsFromFetchResult:(PHFetchResult *)result completion:(void (^)(NSArray<TZAssetModel *> *))completion {
TZImagePickerConfig *config = [TZImagePickerConfig sharedInstance];
return [self getAssetsFromFetchResult:result allowPickingVideo:config.allowPickingVideo allowPickingImage:config.allowPickingImage completion:completion];
}
- (void)getAssetsFromFetchResult:(id)result allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(NSArray<TZAssetModel *> *))completion {
- (void)getAssetsFromFetchResult:(PHFetchResult *)result allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(NSArray<TZAssetModel *> *))completion {
NSMutableArray *photoArr = [NSMutableArray array];
if ([result isKindOfClass:[PHFetchResult class]]) {
PHFetchResult *fetchResult = (PHFetchResult *)result;
[fetchResult enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
TZAssetModel *model = [self assetModelWithAsset:obj allowPickingVideo:allowPickingVideo allowPickingImage:allowPickingImage];
[result enumerateObjectsUsingBlock:^(PHAsset *asset, NSUInteger idx, BOOL * _Nonnull stop) {
TZAssetModel *model = [self assetModelWithAsset:asset allowPickingVideo:allowPickingVideo allowPickingImage:allowPickingImage];
if (model) {
[photoArr addObject:model];
}
}];
if (completion) completion(photoArr);
} else if ([result isKindOfClass:[ALAssetsGroup class]]) {
ALAssetsGroup *group = (ALAssetsGroup *)result;
if (allowPickingImage && allowPickingVideo) {
[group setAssetsFilter:[ALAssetsFilter allAssets]];
} else if (allowPickingVideo) {
[group setAssetsFilter:[ALAssetsFilter allVideos]];
} else if (allowPickingImage) {
[group setAssetsFilter:[ALAssetsFilter allPhotos]];
}
ALAssetsGroupEnumerationResultsBlock resultBlock = ^(ALAsset *result, NSUInteger index, BOOL *stop) {
if (result == nil) {
if (completion) completion(photoArr);
}
TZAssetModel *model = [self assetModelWithAsset:result allowPickingVideo:allowPickingVideo allowPickingImage:allowPickingImage];
if (model) {
[photoArr addObject:model];
}
};
if (self.sortAscendingByModificationDate) {
[group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
if (resultBlock) { resultBlock(result,index,stop); }
}];
} else {
[group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
if (resultBlock) { resultBlock(result,index,stop); }
}];
}
}
}
/// Get asset at index 获得下标为index的单个照片
/// if index beyond bounds, return nil in callback 如果索引越界, 在回调中返回 nil
- (void)getAssetFromFetchResult:(id)result atIndex:(NSInteger)index allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(TZAssetModel *))completion {
if ([result isKindOfClass:[PHFetchResult class]]) {
PHFetchResult *fetchResult = (PHFetchResult *)result;
- (void)getAssetFromFetchResult:(PHFetchResult *)result atIndex:(NSInteger)index allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(TZAssetModel *))completion {
PHAsset *asset;
@try {
asset = fetchResult[index];
asset = result[index];
}
@catch (NSException* e) {
if (completion) completion(nil);
......@@ -294,30 +196,9 @@ static dispatch_once_t onceToken;
}
TZAssetModel *model = [self assetModelWithAsset:asset allowPickingVideo:allowPickingVideo allowPickingImage:allowPickingImage];
if (completion) completion(model);
} else if ([result isKindOfClass:[ALAssetsGroup class]]) {
ALAssetsGroup *group = (ALAssetsGroup *)result;
if (allowPickingImage && allowPickingVideo) {
[group setAssetsFilter:[ALAssetsFilter allAssets]];
} else if (allowPickingVideo) {
[group setAssetsFilter:[ALAssetsFilter allVideos]];
} else if (allowPickingImage) {
[group setAssetsFilter:[ALAssetsFilter allPhotos]];
}
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:index];
@try {
[group enumerateAssetsAtIndexes:indexSet options:NSEnumerationConcurrent usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
if (!result) return;
TZAssetModel *model = [self assetModelWithAsset:result allowPickingVideo:allowPickingVideo allowPickingImage:allowPickingImage];
if (completion) completion(model);
}];
}
@catch (NSException* e) {
if (completion) completion(nil);
}
}
}
- (TZAssetModel *)assetModelWithAsset:(id)asset allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage {
- (TZAssetModel *)assetModelWithAsset:(PHAsset *)asset allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage {
BOOL canSelect = YES;
if ([self.pickerDelegate respondsToSelector:@selector(isAssetCanSelect:)]) {
canSelect = [self.pickerDelegate isAssetCanSelect:asset];
......@@ -326,7 +207,6 @@ static dispatch_once_t onceToken;
TZAssetModel *model;
TZAssetModelMediaType type = [self getAssetType:asset];
if ([asset isKindOfClass:[PHAsset class]]) {
if (!allowPickingVideo && type == TZAssetModelMediaTypeVideo) return nil;
if (!allowPickingImage && type == TZAssetModelMediaTypePhoto) return nil;
if (!allowPickingImage && type == TZAssetModelMediaTypePhotoGif) return nil;
......@@ -341,33 +221,11 @@ static dispatch_once_t onceToken;
NSString *timeLength = type == TZAssetModelMediaTypeVideo ? [NSString stringWithFormat:@"%0.0f",phAsset.duration] : @"";
timeLength = [self getNewTimeFromDurationSecond:timeLength.integerValue];
model = [TZAssetModel modelWithAsset:asset type:type timeLength:timeLength];
} else {
if (!allowPickingVideo){
model = [TZAssetModel modelWithAsset:asset type:type];
return model;
}
/// Allow picking video
if (type == TZAssetModelMediaTypeVideo) {
NSTimeInterval duration = [[asset valueForProperty:ALAssetPropertyDuration] doubleValue];
NSString *timeLength = [NSString stringWithFormat:@"%0.0f",duration];
timeLength = [self getNewTimeFromDurationSecond:timeLength.integerValue];
model = [TZAssetModel modelWithAsset:asset type:type timeLength:timeLength];
} else {
if (self.hideWhenCanNotSelect) {
// 过滤掉尺寸不满足要求的图片
if (![self isPhotoSelectableWithAsset:asset]) {
return nil;
}
}
model = [TZAssetModel modelWithAsset:asset type:type];
}
}
return model;
}
- (TZAssetModelMediaType)getAssetType:(id)asset {
- (TZAssetModelMediaType)getAssetType:(PHAsset *)asset {
TZAssetModelMediaType type = TZAssetModelMediaTypePhoto;
if ([asset isKindOfClass:[PHAsset class]]) {
PHAsset *phAsset = (PHAsset *)asset;
if (phAsset.mediaType == PHAssetMediaTypeVideo) type = TZAssetModelMediaTypeVideo;
else if (phAsset.mediaType == PHAssetMediaTypeAudio) type = TZAssetModelMediaTypeAudio;
......@@ -380,11 +238,6 @@ static dispatch_once_t onceToken;
type = TZAssetModelMediaTypePhotoGif;
}
}
} else {
if ([[asset valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypeVideo]) {
type = TZAssetModelMediaTypeVideo;
}
}
return type;
}
......@@ -416,7 +269,6 @@ static dispatch_once_t onceToken;
__block NSInteger assetCount = 0;
for (NSInteger i = 0; i < photos.count; i++) {
TZAssetModel *model = photos[i];
if ([model.asset isKindOfClass:[PHAsset class]]) {
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.resizeMode = PHImageRequestOptionsResizeModeFast;
options.networkAccessAllowed = YES;
......@@ -431,14 +283,6 @@ static dispatch_once_t onceToken;
if (completion) completion(bytes);
}
}];
} else if ([model.asset isKindOfClass:[ALAsset class]]) {
ALAssetRepresentation *representation = [model.asset defaultRepresentation];
if (model.type != TZAssetModelMediaTypeVideo) dataLength += (NSInteger)representation.size;
if (i >= photos.count - 1) {
NSString *bytes = [self getBytesFromDataLength:dataLength];
if (completion) completion(bytes);
}
}
}
}
......@@ -457,7 +301,7 @@ static dispatch_once_t onceToken;
#pragma mark - Get Photo
/// Get photo 获得照片本身
- (int32_t)getPhotoWithAsset:(id)asset completion:(void (^)(UIImage *, NSDictionary *, BOOL isDegraded))completion {
- (int32_t)getPhotoWithAsset:(PHAsset *)asset completion:(void (^)(UIImage *, NSDictionary *, BOOL isDegraded))completion {
CGFloat fullScreenWidth = TZScreenWidth;
if (fullScreenWidth > _photoPreviewMaxWidth) {
fullScreenWidth = _photoPreviewMaxWidth;
......@@ -465,20 +309,19 @@ static dispatch_once_t onceToken;
return [self getPhotoWithAsset:asset photoWidth:fullScreenWidth completion:completion progressHandler:nil networkAccessAllowed:YES];
}
- (int32_t)getPhotoWithAsset:(id)asset photoWidth:(CGFloat)photoWidth completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion {
- (int32_t)getPhotoWithAsset:(PHAsset *)asset photoWidth:(CGFloat)photoWidth completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion {
return [self getPhotoWithAsset:asset photoWidth:photoWidth completion:completion progressHandler:nil networkAccessAllowed:YES];
}
- (int32_t)getPhotoWithAsset:(id)asset completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler networkAccessAllowed:(BOOL)networkAccessAllowed {
- (int32_t)getPhotoWithAsset:(PHAsset *)asset completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler networkAccessAllowed:(BOOL)networkAccessAllowed {
CGFloat fullScreenWidth = TZScreenWidth;
if (fullScreenWidth > _photoPreviewMaxWidth) {
if (_photoPreviewMaxWidth > 0 && fullScreenWidth > _photoPreviewMaxWidth) {
fullScreenWidth = _photoPreviewMaxWidth;
}
return [self getPhotoWithAsset:asset photoWidth:fullScreenWidth completion:completion progressHandler:progressHandler networkAccessAllowed:networkAccessAllowed];
}
- (int32_t)requestImageDataForAsset:(id)asset completion:(void (^)(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler {
if ([asset isKindOfClass:[PHAsset class]]) {
- (int32_t)requestImageDataForAsset:(PHAsset *)asset completion:(void (^)(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler {
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
dispatch_async(dispatch_get_main_queue(), ^{
......@@ -493,22 +336,9 @@ static dispatch_once_t onceToken;
if (completion) completion(imageData,dataUTI,orientation,info);
}];
return imageRequestID;
} else if ([asset isKindOfClass:[ALAsset class]]) {
ALAsset *alAsset = (ALAsset *)asset;
dispatch_async(dispatch_get_global_queue(0,0), ^{
ALAssetRepresentation *assetRep = [alAsset defaultRepresentation];
CGImageRef fullScrennImageRef = [assetRep fullScreenImage];
UIImage *fullScrennImage = [UIImage imageWithCGImage:fullScrennImageRef scale:2.0 orientation:UIImageOrientationUp];
dispatch_async(dispatch_get_main_queue(), ^{
if (completion) completion(UIImageJPEGRepresentation(fullScrennImage, 0.83), nil, UIImageOrientationUp, nil);
});
});
}
return 0;
}
- (int32_t)getPhotoWithAsset:(id)asset photoWidth:(CGFloat)photoWidth completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler networkAccessAllowed:(BOOL)networkAccessAllowed {
if ([asset isKindOfClass:[PHAsset class]]) {
- (int32_t)getPhotoWithAsset:(PHAsset *)asset photoWidth:(CGFloat)photoWidth completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler networkAccessAllowed:(BOOL)networkAccessAllowed {
CGSize imageSize;
if (photoWidth < TZScreenWidth && photoWidth < _photoPreviewMaxWidth) {
imageSize = AssetGridThumbnailSize;
......@@ -555,7 +385,7 @@ static dispatch_once_t onceToken;
options.networkAccessAllowed = YES;
options.resizeMode = PHImageRequestOptionsResizeModeFast;
[[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
UIImage *resultImage = [UIImage imageWithData:imageData scale:0.1];
UIImage *resultImage = [UIImage imageWithData:imageData];
if (![TZImagePickerConfig sharedInstance].notScaleImage) {
resultImage = [self scaleImage:resultImage toSize:imageSize];
}
......@@ -568,34 +398,10 @@ static dispatch_once_t onceToken;
}
}];
return imageRequestID;
} else if ([asset isKindOfClass:[ALAsset class]]) {
ALAsset *alAsset = (ALAsset *)asset;
dispatch_async(dispatch_get_global_queue(0,0), ^{
CGImageRef thumbnailImageRef = alAsset.thumbnail;
UIImage *thumbnailImage = [UIImage imageWithCGImage:thumbnailImageRef scale:2.0 orientation:UIImageOrientationUp];
dispatch_async(dispatch_get_main_queue(), ^{
if (completion) completion(thumbnailImage,nil,YES);
if (photoWidth == TZScreenWidth || photoWidth == self->_photoPreviewMaxWidth) {
dispatch_async(dispatch_get_global_queue(0,0), ^{
ALAssetRepresentation *assetRep = [alAsset defaultRepresentation];
CGImageRef fullScrennImageRef = [assetRep fullScreenImage];
UIImage *fullScrennImage = [UIImage imageWithCGImage:fullScrennImageRef scale:2.0 orientation:UIImageOrientationUp];
dispatch_async(dispatch_get_main_queue(), ^{
if (completion) completion(fullScrennImage,nil,NO);
});
});
}
});
});
}
return 0;
}
/// Get postImage / 获取封面图
- (void)getPostImageWithAlbumModel:(TZAlbumModel *)model completion:(void (^)(UIImage *))completion {
if (iOS8Later) {
id asset = [model.result lastObject];
if (!self.sortAscendingByModificationDate) {
asset = [model.result firstObject];
......@@ -603,15 +409,10 @@ static dispatch_once_t onceToken;
[[TZImageManager manager] getPhotoWithAsset:asset photoWidth:80 completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) {
if (completion) completion(photo);
}];
} else {
ALAssetsGroup *group = model.result;
UIImage *postImage = [UIImage imageWithCGImage:group.posterImage];
if (completion) completion(postImage);
}
}
/// Get Original Photo / 获取原图
- (void)getOriginalPhotoWithAsset:(id)asset completion:(void (^)(UIImage *photo,NSDictionary *info))completion {
- (void)getOriginalPhotoWithAsset:(PHAsset *)asset completion:(void (^)(UIImage *photo,NSDictionary *info))completion {
[self getOriginalPhotoWithAsset:asset newCompletion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) {
if (completion) {
completion(photo,info);
......@@ -619,8 +420,7 @@ static dispatch_once_t onceToken;
}];
}
- (void)getOriginalPhotoWithAsset:(id)asset newCompletion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion {
if ([asset isKindOfClass:[PHAsset class]]) {
- (void)getOriginalPhotoWithAsset:(PHAsset *)asset newCompletion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion {
PHImageRequestOptions *option = [[PHImageRequestOptions alloc]init];
option.networkAccessAllowed = YES;
option.resizeMode = PHImageRequestOptionsResizeModeFast;
......@@ -632,27 +432,13 @@ static dispatch_once_t onceToken;
if (completion) completion(result,info,isDegraded);
}
}];
} else if ([asset isKindOfClass:[ALAsset class]]) {
ALAsset *alAsset = (ALAsset *)asset;
ALAssetRepresentation *assetRep = [alAsset defaultRepresentation];
dispatch_async(dispatch_get_global_queue(0,0), ^{
CGImageRef originalImageRef = [assetRep fullResolutionImage];
UIImage *originalImage = [UIImage imageWithCGImage:originalImageRef scale:1.0 orientation:UIImageOrientationUp];
dispatch_async(dispatch_get_main_queue(), ^{
if (completion) completion(originalImage,nil,NO);
});
});
}
}
- (void)getOriginalPhotoDataWithAsset:(id)asset completion:(void (^)(NSData *data,NSDictionary *info,BOOL isDegraded))completion {
- (void)getOriginalPhotoDataWithAsset:(PHAsset *)asset completion:(void (^)(NSData *data,NSDictionary *info,BOOL isDegraded))completion {
[self getOriginalPhotoDataWithAsset:asset progressHandler:nil completion:completion];
}
- (void)getOriginalPhotoDataWithAsset:(id)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(NSData *data,NSDictionary *info,BOOL isDegraded))completion {
if ([asset isKindOfClass:[PHAsset class]]) {
- (void)getOriginalPhotoDataWithAsset:(PHAsset *)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(NSData *data,NSDictionary *info,BOOL isDegraded))completion {
PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init];
option.networkAccessAllowed = YES;
if ([[asset valueForKey:@"filename"] hasSuffix:@"GIF"]) {
......@@ -667,137 +453,76 @@ static dispatch_once_t onceToken;
if (completion) completion(imageData,info,NO);
}
}];
} else if ([asset isKindOfClass:[ALAsset class]]) {
ALAsset *alAsset = (ALAsset *)asset;
ALAssetRepresentation *assetRep = [alAsset defaultRepresentation];
Byte *imageBuffer = (Byte *)malloc(assetRep.size);
NSUInteger bufferSize = [assetRep getBytes:imageBuffer fromOffset:0.0 length:assetRep.size error:nil];
NSData *imageData = [NSData dataWithBytesNoCopy:imageBuffer length:bufferSize freeWhenDone:YES];
if (completion) completion(imageData,nil,NO);
}
}
#pragma mark - Save photo
- (void)savePhotoWithImage:(UIImage *)image completion:(void (^)(NSError *error))completion {
- (void)savePhotoWithImage:(UIImage *)image completion:(void (^)(PHAsset *asset, NSError *error))completion {
[self savePhotoWithImage:image location:nil completion:completion];
}
- (void)savePhotoWithImage:(UIImage *)image location:(CLLocation *)location completion:(void (^)(NSError *error))completion {
if (iOS8Later) {
- (void)savePhotoWithImage:(UIImage *)image location:(CLLocation *)location completion:(void (^)(PHAsset *asset, NSError *error))completion {
__block NSString *localIdentifier = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
if (@available(iOS 9, *)) {
NSData *data = UIImageJPEGRepresentation(image, 0.9);
PHAssetResourceCreationOptions *options = [[PHAssetResourceCreationOptions alloc] init];
options.shouldMoveFile = YES;
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAsset];
[request addResourceWithType:PHAssetResourceTypePhoto data:data options:options];
if (location) {
request.location = location;
}
request.creationDate = [NSDate date];
} else {
PHAssetChangeRequest *request = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
localIdentifier = request.placeholderForCreatedAsset.localIdentifier;
if (location) {
request.location = location;
}
request.creationDate = [NSDate date];
}
} completionHandler:^(BOOL success, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (success && completion) {
completion(nil);
PHAsset *asset = [[PHAsset fetchAssetsWithLocalIdentifiers:@[localIdentifier] options:nil] firstObject];
completion(asset, nil);
} else if (error) {
NSLog(@"保存照片出错:%@",error.localizedDescription);
if (completion) {
completion(error);
completion(nil, error);
}
}
});
}];
} else {
[self.assetLibrary writeImageToSavedPhotosAlbum:image.CGImage orientation:[self orientationFromImage:image] completionBlock:^(NSURL *assetURL, NSError *error) {
if (error) {
NSLog(@"保存图片失败:%@",error.localizedDescription);
if (completion) {
completion(error);
}
} else {
// 多给系统0.5秒的时间,让系统去更新相册数据
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (completion) {
completion(nil);
}
});
}
}];
}
}
#pragma mark - Save video
- (void)saveVideoWithUrl:(NSURL *)url completion:(void (^)(NSError *error))completion {
- (void)saveVideoWithUrl:(NSURL *)url completion:(void (^)(PHAsset *asset, NSError *error))completion {
[self saveVideoWithUrl:url location:nil completion:completion];
}
- (void)saveVideoWithUrl:(NSURL *)url location:(CLLocation *)location completion:(void (^)(NSError *error))completion {
if (iOS8Later) {
- (void)saveVideoWithUrl:(NSURL *)url location:(CLLocation *)location completion:(void (^)(PHAsset *asset, NSError *error))completion {
__block NSString *localIdentifier = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
if (@available(iOS 9, *)) {
PHAssetResourceCreationOptions *options = [[PHAssetResourceCreationOptions alloc] init];
options.shouldMoveFile = YES;
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAsset];
[request addResourceWithType:PHAssetResourceTypeVideo fileURL:url options:options];
if (location) {
request.location = location;
}
request.creationDate = [NSDate date];
} else {
PHAssetChangeRequest *request = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:url];
localIdentifier = request.placeholderForCreatedAsset.localIdentifier;
if (location) {
request.location = location;
}
request.creationDate = [NSDate date];
}
} completionHandler:^(BOOL success, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (success && completion) {
completion(nil);
PHAsset *asset = [[PHAsset fetchAssetsWithLocalIdentifiers:@[localIdentifier] options:nil] firstObject];
completion(asset, nil);
} else if (error) {
NSLog(@"保存视频出错:%@",error.localizedDescription);
if (completion) {
completion(error);
completion(nil, error);
}
}
});
}];
} else {
[self.assetLibrary writeVideoAtPathToSavedPhotosAlbum:url completionBlock:^(NSURL *assetURL, NSError *error) {
if (error) {
NSLog(@"保存视频出错:%@",error.localizedDescription);
if (completion) {
completion(error);
}
} else {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (completion) {
completion(nil);
}
});
}
}];
}
}
#pragma mark - Get Video
/// Get Video / 获取视频
- (void)getVideoWithAsset:(id)asset completion:(void (^)(AVPlayerItem *, NSDictionary *))completion {
- (void)getVideoWithAsset:(PHAsset *)asset completion:(void (^)(AVPlayerItem *, NSDictionary *))completion {
[self getVideoWithAsset:asset progressHandler:nil completion:completion];
}
- (void)getVideoWithAsset:(id)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(AVPlayerItem *, NSDictionary *))completion {
if ([asset isKindOfClass:[PHAsset class]]) {
- (void)getVideoWithAsset:(PHAsset *)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(AVPlayerItem *, NSDictionary *))completion {
PHVideoRequestOptions *option = [[PHVideoRequestOptions alloc] init];
option.networkAccessAllowed = YES;
option.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
......@@ -810,25 +535,16 @@ static dispatch_once_t onceToken;
[[PHImageManager defaultManager] requestPlayerItemForVideo:asset options:option resultHandler:^(AVPlayerItem *playerItem, NSDictionary *info) {
if (completion) completion(playerItem,info);
}];
} else if ([asset isKindOfClass:[ALAsset class]]) {
ALAsset *alAsset = (ALAsset *)asset;
ALAssetRepresentation *defaultRepresentation = [alAsset defaultRepresentation];
NSString *uti = [defaultRepresentation UTI];
NSURL *videoURL = [[asset valueForProperty:ALAssetPropertyURLs] valueForKey:uti];
AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithURL:videoURL];
if (completion && playerItem) completion(playerItem,nil);
}
}
#pragma mark - Export video
/// Export Video / 导出视频
- (void)getVideoOutputPathWithAsset:(id)asset success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure {
- (void)getVideoOutputPathWithAsset:(PHAsset *)asset success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure {
[self getVideoOutputPathWithAsset:asset presetName:AVAssetExportPreset640x480 success:success failure:failure];
}
- (void)getVideoOutputPathWithAsset:(id)asset presetName:(NSString *)presetName success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure {
if ([asset isKindOfClass:[PHAsset class]]) {
- (void)getVideoOutputPathWithAsset:(PHAsset *)asset presetName:(NSString *)presetName success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure {
PHVideoRequestOptions* options = [[PHVideoRequestOptions alloc] init];
options.version = PHVideoRequestOptionsVersionOriginal;
options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
......@@ -839,15 +555,10 @@ static dispatch_once_t onceToken;
// NSLog(@"AVAsset URL: %@",myAsset.URL);
[self startExportVideoWithVideoAsset:videoAsset presetName:presetName success:success failure:failure];
}];
} else if ([asset isKindOfClass:[ALAsset class]]) {
NSURL *videoURL =[asset valueForProperty:ALAssetPropertyAssetURL]; // ALAssetPropertyURLs
AVURLAsset *videoAsset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
[self startExportVideoWithVideoAsset:videoAsset presetName:presetName success:success failure:failure];
}
}
/// Deprecated, Use -getVideoOutputPathWithAsset:failure:success:
- (void)getVideoOutputPathWithAsset:(id)asset completion:(void (^)(NSString *outputPath))completion {
- (void)getVideoOutputPathWithAsset:(PHAsset *)asset completion:(void (^)(NSString *outputPath))completion {
[self getVideoOutputPathWithAsset:asset success:completion failure:nil];
}
......@@ -939,21 +650,7 @@ static dispatch_once_t onceToken;
}
}
/// Judge is a assets array contain the asset 判断一个assets数组是否包含这个asset
- (BOOL)isAssetsArray:(NSArray *)assets containAsset:(id)asset {
if (iOS8Later) {
return [assets containsObject:asset];
} else {
NSMutableArray *selectedAssetUrls = [NSMutableArray array];
for (ALAsset *asset_item in assets) {
[selectedAssetUrls addObject:[asset_item valueForProperty:ALAssetPropertyURLs]];
}
return [selectedAssetUrls containsObject:[asset valueForProperty:ALAssetPropertyURLs]];
}
}
- (BOOL)isCameraRollAlbum:(id)metadata {
if ([metadata isKindOfClass:[PHAssetCollection class]]) {
- (BOOL)isCameraRollAlbum:(PHAssetCollection *)metadata {
NSString *versionStr = [[UIDevice currentDevice].systemVersion stringByReplacingOccurrencesOfString:@"." withString:@""];
if (versionStr.length <= 1) {
versionStr = [versionStr stringByAppendingString:@"00"];
......@@ -967,59 +664,25 @@ static dispatch_once_t onceToken;
} else {
return ((PHAssetCollection *)metadata).assetCollectionSubtype == PHAssetCollectionSubtypeSmartAlbumUserLibrary;
}
}
if ([metadata isKindOfClass:[ALAssetsGroup class]]) {
ALAssetsGroup *group = metadata;
return ([[group valueForProperty:ALAssetsGroupPropertyType] intValue] == ALAssetsGroupSavedPhotos);
}
return NO;
}
- (NSString *)getAssetIdentifier:(id)asset {
if (iOS8Later) {
PHAsset *phAsset = (PHAsset *)asset;
return phAsset.localIdentifier;
} else {
ALAsset *alAsset = (ALAsset *)asset;
NSURL *assetUrl = [alAsset valueForProperty:ALAssetPropertyAssetURL];
return assetUrl.absoluteString;
}
}
/// 检查照片大小是否满足最小要求
- (BOOL)isPhotoSelectableWithAsset:(id)asset {
CGSize photoSize = [self photoSizeWithAsset:asset];
- (BOOL)isPhotoSelectableWithAsset:(PHAsset *)asset {
CGSize photoSize = CGSizeMake(asset.pixelWidth, asset.pixelHeight);
if (self.minPhotoWidthSelectable > photoSize.width || self.minPhotoHeightSelectable > photoSize.height) {
return NO;
}
return YES;
}
- (CGSize)photoSizeWithAsset:(id)asset {
if (iOS8Later) {
PHAsset *phAsset = (PHAsset *)asset;
return CGSizeMake(phAsset.pixelWidth, phAsset.pixelHeight);
} else {
ALAsset *alAsset = (ALAsset *)asset;
return alAsset.defaultRepresentation.dimensions;
}
}
#pragma mark - Private Method
- (TZAlbumModel *)modelWithResult:(id)result name:(NSString *)name isCameraRoll:(BOOL)isCameraRoll needFetchAssets:(BOOL)needFetchAssets {
- (TZAlbumModel *)modelWithResult:(PHFetchResult *)result name:(NSString *)name isCameraRoll:(BOOL)isCameraRoll needFetchAssets:(BOOL)needFetchAssets {
TZAlbumModel *model = [[TZAlbumModel alloc] init];
[model setResult:result needFetchAssets:needFetchAssets];
model.name = name;
model.isCameraRoll = isCameraRoll;
if ([result isKindOfClass:[PHFetchResult class]]) {
PHFetchResult *fetchResult = (PHFetchResult *)result;
model.count = fetchResult.count;
} else if ([result isKindOfClass:[ALAssetsGroup class]]) {
ALAssetsGroup *group = (ALAssetsGroup *)result;
model.count = [group numberOfAssets];
}
model.count = result.count;
return model;
}
......@@ -1050,20 +713,16 @@ static dispatch_once_t onceToken;
}
/// 判断asset是否是视频
- (BOOL)isVideo:(id)asset {
if (iOS8Later) {
PHAsset *phAsset = asset;
return phAsset.mediaType == PHAssetMediaTypeVideo;
} else {
ALAsset *alAsset = asset;
NSString *alAssetType = [[alAsset valueForProperty:ALAssetPropertyType] stringValue];
return [alAssetType isEqualToString:ALAssetTypeVideo];
}
- (BOOL)isVideo:(PHAsset *)asset {
return asset.mediaType == PHAssetMediaTypeVideo;
}
- (ALAssetOrientation)orientationFromImage:(UIImage *)image {
NSInteger orientation = image.imageOrientation;
return orientation;
- (TZAssetModel *)createModelWithAsset:(PHAsset *)asset {
TZAssetModelMediaType type = [[TZImageManager manager] getAssetType:asset];
NSString *timeLength = type == TZAssetModelMediaTypeVideo ? [NSString stringWithFormat:@"%0.0f",asset.duration] : @"";
timeLength = [[TZImageManager manager] getNewTimeFromDurationSecond:timeLength.integerValue];
TZAssetModel *model = [TZAssetModel modelWithAsset:asset type:type timeLength:timeLength];
return model;
}
/// 获取优化后的视频转向信息
......
......@@ -4,7 +4,7 @@
//
// Created by 谭真 on 15/12/24.
// Copyright © 2015年 谭真. All rights reserved.
// version 2.2.6 - 2018.08.21
// version 3.0.9 - 2018.10.09
// 更多信息,请前往项目的github地址:https://github.com/banchichen/TZImagePickerController
/*
......@@ -24,9 +24,7 @@
#import "TZGifPhotoPreviewController.h"
#import "TZLocationManager.h"
#import "TZPhotoPreviewController.h"
#define iOS7Later ([UIDevice currentDevice].systemVersion.floatValue >= 7.0f)
#define iOS8Later ([UIDevice currentDevice].systemVersion.floatValue >= 8.0f)
#import "TZPhotoPreviewCell.h"
@class TZAlbumCell, TZAssetCell;
@protocol TZImagePickerControllerDelegate;
......@@ -40,7 +38,7 @@
/// This init method just for previewing photos / 用这个初始化方法以预览图片
- (instancetype)initWithSelectedAssets:(NSMutableArray *)selectedAssets selectedPhotos:(NSMutableArray *)selectedPhotos index:(NSInteger)index;
/// This init method for crop photo / 用这个初始化方法以裁剪图片
- (instancetype)initCropTypeWithAsset:(id)asset photo:(UIImage *)photo completion:(void (^)(UIImage *cropImage,id asset))completion;
- (instancetype)initCropTypeWithAsset:(PHAsset *)asset photo:(UIImage *)photo completion:(void (^)(UIImage *cropImage,PHAsset *asset))completion;
#pragma mark -
/// Default is 9 / 默认最大可选9张图片
......@@ -185,8 +183,8 @@
@property (nonatomic, copy) void (^albumCellDidLayoutSubviewsBlock)(TZAlbumCell *cell, UIImageView *posterImageView, UILabel *titleLabel);
#pragma mark -
- (id)showAlertWithTitle:(NSString *)title;
- (void)hideAlertView:(id)alertView;
- (UIAlertController *)showAlertWithTitle:(NSString *)title;
- (void)hideAlertView:(UIAlertController *)alertView;
- (void)showProgressHUD;
- (void)hideProgressHUD;
@property (nonatomic, assign) BOOL isSelectOriginalPhoto;
......@@ -247,10 +245,8 @@
@property (nonatomic, copy) void (^imagePickerControllerDidCancelHandle)(void);
// If user picking a video, this handle will be called.
// If system version > iOS8,asset is kind of PHAsset class, else is ALAsset class.
// 如果用户选择了一个视频,下面的handle会被执行
// 如果系统版本大于iOS8,asset是PHAsset类的对象,否则是ALAsset类的对象
@property (nonatomic, copy) void (^didFinishPickingVideoHandle)(UIImage *coverImage,id asset);
@property (nonatomic, copy) void (^didFinishPickingVideoHandle)(UIImage *coverImage,PHAsset *asset);
// If user picking a gif image, this callback will be called.
// 如果用户选择了一个gif图片,下面的handle会被执行
......@@ -279,22 +275,20 @@
- (void)tz_imagePickerControllerDidCancel:(TZImagePickerController *)picker;
// If user picking a video, this callback will be called.
// If system version > iOS8,asset is kind of PHAsset class, else is ALAsset class.
// 如果用户选择了一个视频,下面的handle会被执行
// 如果系统版本大于iOS8,asset是PHAsset类的对象,否则是ALAsset类的对象
- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingVideo:(UIImage *)coverImage sourceAssets:(id)asset;
- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingVideo:(UIImage *)coverImage sourceAssets:(PHAsset *)asset;
// If user picking a gif image, this callback will be called.
// 如果用户选择了一个gif图片,下面的handle会被执行
- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingGifImage:(UIImage *)animatedImage sourceAssets:(id)asset;
- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingGifImage:(UIImage *)animatedImage sourceAssets:(PHAsset *)asset;
// Decide album show or not't
// 决定相册显示与否 albumName:相册名字 result:相册原始数据
- (BOOL)isAlbumCanSelect:(NSString *)albumName result:(id)result;
- (BOOL)isAlbumCanSelect:(NSString *)albumName result:(PHFetchResult *)result;
// Decide asset show or not't
// 决定照片显示与否
- (BOOL)isAssetCanSelect:(id)asset;
- (BOOL)isAssetCanSelect:(PHAsset *)asset;
@end
......@@ -310,17 +304,12 @@
@end
@interface NSString (TzExtension)
- (BOOL)tz_containsString:(NSString *)string;
- (CGSize)tz_calculateSizeWithAttributes:(NSDictionary *)attributes maxSize:(CGSize)maxSize;
@end
@interface TZCommonTools : NSObject
+ (BOOL)tz_isIPhoneX;
+ (CGFloat)tz_statusBarHeight;
// 获得Info.plist数据字典
+ (NSDictionary *)tz_getInfoDictionary;
+ (BOOL)isRightToLeftLayout;
@end
......@@ -330,10 +319,13 @@
@property(nonatomic, assign) BOOL allowPickingImage;
@property (nonatomic, assign) BOOL allowPickingVideo;
@property (strong, nonatomic) NSBundle *languageBundle;
/// 默认是200,如果一个GIF过大,里面图片个数可能超过1000,会导致内存飙升而崩溃
@property (assign, nonatomic) NSInteger gifPreviewMaxImagesCount;
@property (assign, nonatomic) BOOL showSelectedIndex;
@property (assign, nonatomic) BOOL showPhotoCannotSelectLayer;
@property (assign, nonatomic) BOOL notScaleImage;
@property (assign, nonatomic) BOOL needFixComposition;
/// 默认是50,如果一个GIF过大,里面图片个数可能超过1000,会导致内存飙升而崩溃
@property (assign, nonatomic) NSInteger gifPreviewMaxImagesCount;
/// 【自定义GIF播放方案】为了避免内存过大,内部默认限制只播放50帧(平均取),可通过gifPreviewMaxImagesCount属性调整,若对GIF预览有更好的效果要求,可实现这个block采用FLAnimatedImage等三方库来播放,但注意FLAnimatedImage有播放速度较慢问题,自行取舍下。
@property (nonatomic, copy) void (^gifImagePlayBlock)(TZPhotoPreviewView *view, UIImageView *imageView, NSData *gifData, NSDictionary *info);
@end
......@@ -4,7 +4,7 @@
//
// Created by 谭真 on 15/12/24.
// Copyright © 2015年 谭真. All rights reserved.
// version 2.2.6 - 2018.08.21
// version 3.0.9 - 2018.10.09
// 更多信息,请前往项目的github地址:https://github.com/banchichen/TZImagePickerController
#import "TZImagePickerController.h"
......@@ -14,7 +14,6 @@
#import "TZAssetCell.h"
#import "UIView+Layout.h"
#import "TZImageManager.h"
#import <sys/utsname.h>
@interface TZImagePickerController () {
NSTimer *_timer;
......@@ -60,19 +59,15 @@
self.oKButtonTitleColorNormal = [UIColor colorWithRed:(83/255.0) green:(179/255.0) blue:(17/255.0) alpha:1.0];
self.oKButtonTitleColorDisabled = [UIColor colorWithRed:(83/255.0) green:(179/255.0) blue:(17/255.0) alpha:0.5];
if (iOS7Later) {
self.navigationBar.barTintColor = [UIColor colorWithRed:(34/255.0) green:(34/255.0) blue:(34/255.0) alpha:1.0];
self.navigationBar.tintColor = [UIColor whiteColor];
self.automaticallyAdjustsScrollViewInsets = NO;
if (self.needShowStatusBar) [UIApplication sharedApplication].statusBarHidden = NO;
}
}
- (void)setNaviBgColor:(UIColor *)naviBgColor {
_naviBgColor = naviBgColor;
if (iOS7Later) {
self.navigationBar.barTintColor = naviBgColor;
}
}
- (void)setNaviTitleColor:(UIColor *)naviTitleColor {
......@@ -110,9 +105,9 @@
_isStatusBarDefault = isStatusBarDefault;
if (isStatusBarDefault) {
self.statusBarStyle = iOS7Later ? UIStatusBarStyleDefault : UIStatusBarStyleBlackOpaque;
self.statusBarStyle = UIStatusBarStyleDefault;
} else {
self.statusBarStyle = iOS7Later ? UIStatusBarStyleLightContent : UIStatusBarStyleBlackOpaque;
self.statusBarStyle = UIStatusBarStyleLightContent;
}
}
......@@ -192,16 +187,14 @@
_tipLabel.text = tipText;
[self.view addSubview:_tipLabel];
if (iOS8Later) {
_settingBtn = [UIButton buttonWithType:UIButtonTypeSystem];
[_settingBtn setTitle:self.settingBtnTitleStr forState:UIControlStateNormal];
_settingBtn.frame = CGRectMake(0, 180, self.view.tz_width, 44);
_settingBtn.titleLabel.font = [UIFont systemFontOfSize:18];
[_settingBtn addTarget:self action:@selector(settingBtnClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_settingBtn];
}
if ([TZImageManager authorizationStatus] == 0) {
if ([PHPhotoLibrary authorizationStatus] == 0) {
_timer = [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(observeAuthrizationStatusChange) userInfo:nil repeats:NO];
}
} else {
......@@ -237,7 +230,7 @@
}
/// This init method for crop photo / 用这个初始化方法以裁剪图片
- (instancetype)initCropTypeWithAsset:(id)asset photo:(UIImage *)photo completion:(void (^)(UIImage *cropImage,id asset))completion {
- (instancetype)initCropTypeWithAsset:(PHAsset *)asset photo:(UIImage *)photo completion:(void (^)(UIImage *cropImage,PHAsset *asset))completion {
TZPhotoPreviewController *previewVc = [[TZPhotoPreviewController alloc] init];
self = [super initWithRootViewController:previewVc];
if (self) {
......@@ -370,7 +363,7 @@
- (void)observeAuthrizationStatusChange {
[_timer invalidate];
_timer = nil;
if ([TZImageManager authorizationStatus] == 0) {
if ([PHPhotoLibrary authorizationStatus] == 0) {
_timer = [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(observeAuthrizationStatusChange) userInfo:nil repeats:NO];
}
......@@ -402,27 +395,15 @@
}
}
- (id)showAlertWithTitle:(NSString *)title {
if (iOS8Later) {
- (UIAlertController *)showAlertWithTitle:(NSString *)title {
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:nil preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:[NSBundle tz_localizedStringForKey:@"OK"] style:UIAlertActionStyleDefault handler:nil]];
[self presentViewController:alertController animated:YES completion:nil];
return alertController;
} else {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title message:nil delegate:nil cancelButtonTitle:[NSBundle tz_localizedStringForKey:@"OK"] otherButtonTitles:nil, nil];
[alertView show];
return alertView;
}
}
- (void)hideAlertView:(id)alertView {
if ([alertView isKindOfClass:[UIAlertController class]]) {
UIAlertController *alertC = alertView;
[alertC dismissViewControllerAnimated:YES completion:nil];
} else if ([alertView isKindOfClass:[UIAlertView class]]) {
UIAlertView *alertV = alertView;
[alertV dismissWithClickedButtonIndex:0 animated:YES];
}
- (void)hideAlertView:(UIAlertController *)alertView {
[alertView dismissViewControllerAnimated:YES completion:nil];
alertView = nil;
}
......@@ -450,7 +431,14 @@
[_progressHUD addSubview:_HUDContainer];
}
[_HUDIndicatorView startAnimating];
[[UIApplication sharedApplication].keyWindow addSubview:_progressHUD];
UIWindow *applicationWindow;
if ([[[UIApplication sharedApplication] delegate] respondsToSelector:@selector(window)]) {
applicationWindow = [[[UIApplication sharedApplication] delegate] window];
} else {
applicationWindow = [[UIApplication sharedApplication] keyWindow];
}
[applicationWindow addSubview:_progressHUD];
[self.view setNeedsLayout];
// if over time, dismiss HUD automatic
__weak typeof(self) weakSelf = self;
......@@ -564,7 +552,7 @@
_selectedAssets = selectedAssets;
_selectedModels = [NSMutableArray array];
_selectedAssetIds = [NSMutableArray array];
for (id asset in selectedAssets) {
for (PHAsset *asset in selectedAssets) {
TZAssetModel *model = [TZAssetModel modelWithAsset:asset type:[[TZImageManager manager] getAssetType:asset]];
model.isSelected = YES;
[self addSelectedModel:model];
......@@ -609,9 +597,7 @@
}
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (iOS7Later) {
viewController.automaticallyAdjustsScrollViewInsets = NO;
}
[super pushViewController:viewController animated:animated];
}
......@@ -621,14 +607,12 @@
- (void)addSelectedModel:(TZAssetModel *)model {
[_selectedModels addObject:model];
NSString *assetId = [[TZImageManager manager] getAssetIdentifier:model.asset];
[_selectedAssetIds addObject:assetId];
[_selectedAssetIds addObject:model.asset.localIdentifier];
}
- (void)removeSelectedModel:(TZAssetModel *)model {
[_selectedModels removeObject:model];
NSString *assetId = [[TZImageManager manager] getAssetIdentifier:model.asset];
[_selectedAssetIds removeObject:assetId];
[_selectedAssetIds removeObject:model.asset.localIdentifier];
}
- (UIImage *)createImageWithColor:(UIColor *)color size:(CGSize)size radius:(CGFloat)radius {
......@@ -650,37 +634,26 @@
#pragma mark - UIContentContainer
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[self willInterfaceOrientionChange];
if (size.width > size.height) {
_cropRect = _cropRectLandscape;
} else {
_cropRect = _cropRectPortrait;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.02 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (![UIApplication sharedApplication].statusBarHidden) {
if (self.needShowStatusBar) [UIApplication sharedApplication].statusBarHidden = NO;
}
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[self willInterfaceOrientionChange];
if (toInterfaceOrientation >= 3) {
});
if (size.width > size.height) {
_cropRect = _cropRectLandscape;
} else {
_cropRect = _cropRectPortrait;
}
}
- (void)willInterfaceOrientionChange {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.02 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (![UIApplication sharedApplication].statusBarHidden) {
if (iOS7Later && self.needShowStatusBar) [UIApplication sharedApplication].statusBarHidden = NO;
}
});
}
#pragma mark - Layout
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
_HUDContainer.frame = CGRectMake((self.view.tz_width - 120) / 2, (self.view.tz_height - 90) / 2, 120, 90);
CGFloat progressHUDY = CGRectGetMaxY(self.navigationBar.frame);
_progressHUD.frame = CGRectMake(0, progressHUDY, self.view.tz_width, self.view.tz_height - progressHUDY);
_HUDContainer.frame = CGRectMake((self.view.tz_width - 120) / 2, (_progressHUD.tz_height - 90 - progressHUDY) / 2, 120, 90);
_HUDIndicatorView.frame = CGRectMake(45, 15, 30, 30);
_HUDLabel.frame = CGRectMake(0,40, 120, 50);
}
......@@ -788,6 +761,14 @@
// NSLog(@"%@ dealloc",NSStringFromClass(self.class));
}
- (UIStatusBarStyle)preferredStatusBarStyle {
TZImagePickerController *tzImagePicker = (TZImagePickerController *)self.navigationController;
if (tzImagePicker && [tzImagePicker isKindOfClass:[TZImagePickerController class]]) {
return tzImagePicker.statusBarStyle;
}
return [super preferredStatusBarStyle];
}
#pragma mark - Layout
- (void)viewDidLayoutSubviews {
......@@ -799,7 +780,7 @@
BOOL isStatusBarHidden = [UIApplication sharedApplication].isStatusBarHidden;
if (self.navigationController.navigationBar.isTranslucent) {
top = naviBarHeight;
if (iOS7Later && !isStatusBarHidden) top += [TZCommonTools tz_statusBarHeight];
if (!isStatusBarHidden) top += [TZCommonTools tz_statusBarHeight];
tableViewHeight = self.view.tz_height - top;
} else {
tableViewHeight = self.view.tz_height;
......@@ -856,47 +837,13 @@
@end
@implementation NSString (TzExtension)
- (BOOL)tz_containsString:(NSString *)string {
if (iOS8Later) {
return [self containsString:string];
} else {
NSRange range = [self rangeOfString:string];
return range.location != NSNotFound;
}
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- (CGSize)tz_calculateSizeWithAttributes:(NSDictionary *)attributes maxSize:(CGSize)maxSize {
CGSize size;
if (iOS7Later) {
size = [self boundingRectWithSize:maxSize options:NSStringDrawingUsesFontLeading attributes:attributes context:nil].size;
} else {
size = [self sizeWithFont:attributes[NSFontAttributeName] constrainedToSize:maxSize];
}
return size;
}
#pragma clang diagnostic pop
@end
@implementation TZCommonTools
+ (BOOL)tz_isIPhoneX {
struct utsname systemInfo;
uname(&systemInfo);
NSString *platform = [NSString stringWithCString:systemInfo.machine encoding:NSASCIIStringEncoding];
if ([platform isEqualToString:@"i386"] || [platform isEqualToString:@"x86_64"]) {
// 模拟器下采用屏幕的高度来判断
return (CGSizeEqualToSize([UIScreen mainScreen].bounds.size, CGSizeMake(375, 812)) ||
CGSizeEqualToSize([UIScreen mainScreen].bounds.size, CGSizeMake(812, 375)));
}
// iPhone10,6是美版iPhoneX 感谢hegelsu指出:https://github.com/banchichen/TZImagePickerController/issues/635
BOOL isIPhoneX = [platform isEqualToString:@"iPhone10,3"] || [platform isEqualToString:@"iPhone10,6"];
return isIPhoneX;
CGSizeEqualToSize([UIScreen mainScreen].bounds.size, CGSizeMake(812, 375)) ||
CGSizeEqualToSize([UIScreen mainScreen].bounds.size, CGSizeMake(414, 896)) ||
CGSizeEqualToSize([UIScreen mainScreen].bounds.size, CGSizeMake(896, 414)));
}
+ (CGFloat)tz_statusBarHeight {
......@@ -915,6 +862,21 @@
}
return infoDict ? infoDict : @{};
}
+ (BOOL)isRightToLeftLayout {
if (@available(iOS 9.0, *)) {
if ([UIView userInterfaceLayoutDirectionForSemanticContentAttribute:UISemanticContentAttributeUnspecified] == UIUserInterfaceLayoutDirectionRightToLeft) {
return YES;
}
} else {
NSString *preferredLanguage = [NSLocale preferredLanguages].firstObject;
if ([preferredLanguage hasPrefix:@"ar-"]) {
return YES;
}
}
return NO;
}
@end
......@@ -927,7 +889,7 @@
if (config == nil) {
config = [[TZImagePickerConfig alloc] init];
config.preferredLanguage = nil;
config.gifPreviewMaxImagesCount = 200;
config.gifPreviewMaxImagesCount = 50;
}
});
return config;
......
......@@ -28,9 +28,7 @@
manager = [[self alloc] init];
manager.locationManager = [[CLLocationManager alloc] init];
manager.locationManager.delegate = manager;
if (iOS8Later) {
[manager.locationManager requestWhenInUseAuthorization];
}
});
return manager;
}
......
......@@ -56,9 +56,7 @@ static CGFloat itemMargin = 5;
_imagePickerVc = [[UIImagePickerController alloc] init];
_imagePickerVc.delegate = self;
// set appearance / 改变相册选择页的导航栏外观
if (iOS7Later) {
_imagePickerVc.navigationBar.barTintColor = self.navigationController.navigationBar.barTintColor;
}
_imagePickerVc.navigationBar.tintColor = self.navigationController.navigationBar.tintColor;
UIBarButtonItem *tzBarItem, *BarItem;
if (@available(iOS 9, *)) {
......@@ -103,14 +101,14 @@ static CGFloat itemMargin = 5;
[tzImagePickerVc showProgressHUD];
}
dispatch_async(dispatch_get_global_queue(0, 0), ^{
if (!tzImagePickerVc.sortAscendingByModificationDate && self->_isFirstAppear && iOS8Later && self->_model.isCameraRoll) {
if (!tzImagePickerVc.sortAscendingByModificationDate && self->_isFirstAppear && self->_model.isCameraRoll) {
[[TZImageManager manager] getCameraRollAlbum:tzImagePickerVc.allowPickingVideo allowPickingImage:tzImagePickerVc.allowPickingImage needFetchAssets:YES completion:^(TZAlbumModel *model) {
self->_model = model;
self->_models = [NSMutableArray arrayWithArray:self->_model.models];
[self initSubviews];
}];
} else {
if (self->_showTakePhotoBtn || !iOS8Later || self->_isFirstAppear) {
if (self->_showTakePhotoBtn || self->_isFirstAppear) {
[[TZImageManager manager] getAssetsFromFetchResult:self->_model.result completion:^(NSArray<TZAssetModel *> *models) {
self->_models = [NSMutableArray arrayWithArray:models];
[self initSubviews];
......@@ -147,6 +145,14 @@ static CGFloat itemMargin = 5;
return NO;
}
- (UIStatusBarStyle)preferredStatusBarStyle {
TZImagePickerController *tzImagePicker = (TZImagePickerController *)self.navigationController;
if (tzImagePicker && [tzImagePicker isKindOfClass:[TZImagePickerController class]]) {
return tzImagePicker.statusBarStyle;
}
return [super preferredStatusBarStyle];
}
- (void)configCollectionView {
_layout = [[UICollectionViewFlowLayout alloc] init];
_collectionView = [[TZCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:_layout];
......@@ -183,9 +189,7 @@ static CGFloat itemMargin = 5;
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if (iOS8Later) {
// [self updateCachedAssets];
}
}
- (void)configBottomToolBar {
......@@ -207,7 +211,7 @@ static CGFloat itemMargin = 5;
if (tzImagePickerVc.allowPickingOriginalPhoto) {
_originalPhotoButton = [UIButton buttonWithType:UIButtonTypeCustom];
_originalPhotoButton.imageEdgeInsets = UIEdgeInsetsMake(0, -10, 0, 0);
_originalPhotoButton.imageEdgeInsets = UIEdgeInsetsMake(0, [TZCommonTools isRightToLeftLayout] ? 10 : -10, 0, 0);
[_originalPhotoButton addTarget:self action:@selector(originalPhotoButtonClick) forControlEvents:UIControlEventTouchUpInside];
_originalPhotoButton.titleLabel.font = [UIFont systemFontOfSize:16];
[_originalPhotoButton setTitle:tzImagePickerVc.fullImageBtnTitleStr forState:UIControlStateNormal];
......@@ -283,7 +287,7 @@ static CGFloat itemMargin = 5;
CGFloat toolBarHeight = [TZCommonTools tz_isIPhoneX] ? 50 + (83 - 49) : 50;
if (self.navigationController.navigationBar.isTranslucent) {
top = naviBarHeight;
if (iOS7Later && !isStatusBarHidden) top += [TZCommonTools tz_statusBarHeight];
if (!isStatusBarHidden) top += [TZCommonTools tz_statusBarHeight];
collectionViewHeight = tzImagePickerVc.showSelectBtn ? self.view.tz_height - toolBarHeight - top : self.view.tz_height - top;;
} else {
collectionViewHeight = tzImagePickerVc.showSelectBtn ? self.view.tz_height - toolBarHeight : self.view.tz_height;
......@@ -303,19 +307,19 @@ static CGFloat itemMargin = 5;
if (!self.navigationController.navigationBar.isHidden) {
toolBarTop = self.view.tz_height - toolBarHeight;
} else {
CGFloat navigationHeight = naviBarHeight;
if (iOS7Later) navigationHeight += [TZCommonTools tz_statusBarHeight];
CGFloat navigationHeight = naviBarHeight + [TZCommonTools tz_statusBarHeight];
toolBarTop = self.view.tz_height - toolBarHeight - navigationHeight;
}
_bottomToolBar.frame = CGRectMake(0, toolBarTop, self.view.tz_width, toolBarHeight);
CGFloat previewWidth = [tzImagePickerVc.previewBtnTitleStr tz_calculateSizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16]} maxSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)].width + 2;
CGFloat previewWidth = [tzImagePickerVc.previewBtnTitleStr boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16]} context:nil].size.width + 2;
if (!tzImagePickerVc.allowPreview) {
previewWidth = 0.0;
}
_previewButton.frame = CGRectMake(10, 3, previewWidth, 44);
_previewButton.tz_width = !tzImagePickerVc.showSelectBtn ? 0 : previewWidth;
if (tzImagePickerVc.allowPickingOriginalPhoto) {
CGFloat fullImageWidth = [tzImagePickerVc.fullImageBtnTitleStr tz_calculateSizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:13]} maxSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)].width;
CGFloat fullImageWidth = [tzImagePickerVc.fullImageBtnTitleStr boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:13]} context:nil].size.width;
_originalPhotoButton.frame = CGRectMake(CGRectGetMaxX(_previewButton.frame), 0, fullImageWidth + 56, 50);
_originalPhotoLabel.frame = CGRectMake(fullImageWidth + 46, 0, 80, 50);
}
......@@ -382,7 +386,7 @@ static CGFloat itemMargin = 5;
__block BOOL havenotShowAlert = YES;
[TZImageManager manager].shouldFixOrientation = YES;
__block id alertView;
__block UIAlertController *alertView;
for (NSInteger i = 0; i < tzImagePickerVc.selectedModels.count; i++) {
TZAssetModel *model = tzImagePickerVc.selectedModels[i];
[[TZImageManager manager] getPhotoWithAsset:model.asset completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) {
......@@ -503,8 +507,7 @@ static CGFloat itemMargin = 5;
cell.allowPickingGif = tzImagePickerVc.allowPickingGif;
cell.model = model;
if (model.isSelected && tzImagePickerVc.showSelectedIndex) {
NSString *assetId = [[TZImageManager manager] getAssetIdentifier:model.asset];
cell.index = [tzImagePickerVc.selectedAssetIds indexOfObject:assetId] + 1;
cell.index = [tzImagePickerVc.selectedAssetIds indexOfObject:model.asset.localIdentifier] + 1;
}
cell.showSelectBtn = tzImagePickerVc.showSelectBtn;
cell.allowPreview = tzImagePickerVc.allowPreview;
......@@ -530,7 +533,7 @@ static CGFloat itemMargin = 5;
model.isSelected = NO;
NSArray *selectedModels = [NSArray arrayWithArray:tzImagePickerVc.selectedModels];
for (TZAssetModel *model_item in selectedModels) {
if ([[[TZImageManager manager] getAssetIdentifier:model.asset] isEqualToString:[[TZImageManager manager] getAssetIdentifier:model_item.asset]]) {
if ([model.asset.localIdentifier isEqualToString:model_item.asset.localIdentifier]) {
[tzImagePickerVc removeSelectedModel:model_item];
break;
}
......@@ -608,9 +611,7 @@ static CGFloat itemMargin = 5;
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (iOS8Later) {
// [self updateCachedAssets];
}
}
#pragma mark - Private Method
......@@ -626,7 +627,7 @@ static CGFloat itemMargin = 5;
/// 拍照按钮点击事件
- (void)takePhoto {
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if ((authStatus == AVAuthorizationStatusRestricted || authStatus ==AVAuthorizationStatusDenied) && iOS7Later) {
if ((authStatus == AVAuthorizationStatusRestricted || authStatus ==AVAuthorizationStatusDenied)) {
NSDictionary *infoDict = [TZCommonTools tz_getInfoDictionary];
// 无权限 做一个友好的提示
......@@ -634,16 +635,10 @@ static CGFloat itemMargin = 5;
if (!appName) appName = [infoDict valueForKey:@"CFBundleName"];
NSString *message = [NSString stringWithFormat:[NSBundle tz_localizedStringForKey:@"Please allow %@ to access your camera in \"Settings -> Privacy -> Camera\""],appName];
if (iOS8Later) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:[NSBundle tz_localizedStringForKey:@"Can not use camera"] message:message delegate:self cancelButtonTitle:[NSBundle tz_localizedStringForKey:@"Cancel"] otherButtonTitles:[NSBundle tz_localizedStringForKey:@"Setting"], nil];
[alert show];
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:[NSBundle tz_localizedStringForKey:@"Can not use camera"] message:message delegate:self cancelButtonTitle:[NSBundle tz_localizedStringForKey:@"OK"] otherButtonTitles:nil];
[alert show];
}
} else if (authStatus == AVAuthorizationStatusNotDetermined) {
// fix issue 466, 防止用户首次拍照拒绝授权时相机页黑屏
if (iOS7Later) {
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
if (granted) {
dispatch_async(dispatch_get_main_queue(), ^{
......@@ -654,9 +649,6 @@ static CGFloat itemMargin = 5;
} else {
[self pushImagePickerController];
}
} else {
[self pushImagePickerController];
}
}
// 调用相机
......@@ -686,9 +678,6 @@ static CGFloat itemMargin = 5;
self.imagePickerVc.videoMaximumDuration = tzImagePickerVc.videoMaximumDuration;
}
self.imagePickerVc.mediaTypes= mediaTypes;
if (iOS8Later) {
_imagePickerVc.modalPresentationStyle = UIModalPresentationOverCurrentContext;
}
if (tzImagePickerVc.uiImagePickerControllerSettingBlock) {
tzImagePickerVc.uiImagePickerControllerSettingBlock(_imagePickerVc);
}
......@@ -781,7 +770,7 @@ static CGFloat itemMargin = 5;
}
for (TZAssetModel *model in _models) {
model.isSelected = NO;
if ([[TZImageManager manager] isAssetsArray:selectedAssets containAsset:model.asset]) {
if ([selectedAssets containsObject:model.asset]) {
model.isSelected = YES;
}
}
......@@ -791,10 +780,8 @@ static CGFloat itemMargin = 5;
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 1) { // 去设置界面,开启相机访问权限
if (iOS8Later) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}
}
}
#pragma mark - UIImagePickerControllerDelegate
......@@ -807,9 +794,9 @@ static CGFloat itemMargin = 5;
[imagePickerVc showProgressHUD];
UIImage *photo = [info objectForKey:UIImagePickerControllerOriginalImage];
if (photo) {
[[TZImageManager manager] savePhotoWithImage:photo location:self.location completion:^(NSError *error){
[[TZImageManager manager] savePhotoWithImage:photo location:self.location completion:^(PHAsset *asset, NSError *error){
if (!error) {
[self reloadPhotoArrayWithMediaType:type];
[self addPHAsset:asset];
}
}];
self.location = nil;
......@@ -819,9 +806,9 @@ static CGFloat itemMargin = 5;
[imagePickerVc showProgressHUD];
NSURL *videoUrl = [info objectForKey:UIImagePickerControllerMediaURL];
if (videoUrl) {
[[TZImageManager manager] saveVideoWithUrl:videoUrl location:self.location completion:^(NSError *error) {
[[TZImageManager manager] saveVideoWithUrl:videoUrl location:self.location completion:^(PHAsset *asset, NSError *error) {
if (!error) {
[self reloadPhotoArrayWithMediaType:type];
[self addPHAsset:asset];
}
}];
self.location = nil;
......@@ -829,31 +816,25 @@ static CGFloat itemMargin = 5;
}
}
- (void)reloadPhotoArrayWithMediaType:(NSString *)mediaType {
- (void)addPHAsset:(PHAsset *)asset {
TZAssetModel *assetModel = [[TZImageManager manager] createModelWithAsset:asset];
TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
[[TZImageManager manager] getCameraRollAlbum:tzImagePickerVc.allowPickingVideo allowPickingImage:tzImagePickerVc.allowPickingImage needFetchAssets:NO completion:^(TZAlbumModel *model) {
self->_model = model;
[[TZImageManager manager] getAssetsFromFetchResult:self->_model.result completion:^(NSArray<TZAssetModel *> *models) {
[tzImagePickerVc hideProgressHUD];
TZAssetModel *assetModel;
if (tzImagePickerVc.sortAscendingByModificationDate) {
assetModel = [models lastObject];
[self->_models addObject:assetModel];
[_models addObject:assetModel];
} else {
assetModel = [models firstObject];
[self->_models insertObject:assetModel atIndex:0];
[_models insertObject:assetModel atIndex:0];
}
if (tzImagePickerVc.maxImagesCount <= 1) {
if (tzImagePickerVc.allowCrop) {
if (tzImagePickerVc.allowCrop && asset.mediaType == PHAssetMediaTypeImage) {
TZPhotoPreviewController *photoPreviewVc = [[TZPhotoPreviewController alloc] init];
if (tzImagePickerVc.sortAscendingByModificationDate) {
photoPreviewVc.currentIndex = self->_models.count - 1;
photoPreviewVc.currentIndex = _models.count - 1;
} else {
photoPreviewVc.currentIndex = 0;
}
photoPreviewVc.models = self->_models;
photoPreviewVc.models = _models;
[self pushPhotoPrevireViewController:photoPreviewVc];
} else {
[tzImagePickerVc addSelectedModel:assetModel];
......@@ -863,7 +844,7 @@ static CGFloat itemMargin = 5;
}
if (tzImagePickerVc.selectedModels.count < tzImagePickerVc.maxImagesCount) {
if ([mediaType isEqualToString:@"public.movie"] && !tzImagePickerVc.allowPickingMultipleVideo) {
if (assetModel.type == TZAssetModelMediaTypeVideo && !tzImagePickerVc.allowPickingMultipleVideo) {
// 不能多选视频的情况下,不选中拍摄的视频
} else {
assetModel.isSelected = YES;
......@@ -871,13 +852,11 @@ static CGFloat itemMargin = 5;
[self refreshBottomToolBarStatus];
}
}
self->_collectionView.hidden = YES;
[self->_collectionView reloadData];
_collectionView.hidden = YES;
[_collectionView reloadData];
self->_shouldScrollToBottom = YES;
_shouldScrollToBottom = YES;
[self scrollCollectionViewToBottom];
}];
}];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
......
......@@ -178,7 +178,11 @@
if (!isDegraded) {
self.isRequestingGIF = NO;
self.progressView.hidden = YES;
if ([TZImagePickerConfig sharedInstance].gifImagePlayBlock) {
[TZImagePickerConfig sharedInstance].gifImagePlayBlock(self, self.imageView, data, info);
} else {
self.imageView.image = [UIImage sd_tz_animatedGIFWithData:data];
}
[self resizeSubviews];
}
}];
......@@ -188,7 +192,7 @@
}
}
- (void)setAsset:(id)asset {
- (void)setAsset:(PHAsset *)asset {
if (_asset && self.imageRequestID) {
[[PHImageManager defaultManager] cancelImageRequest:self.imageRequestID];
}
......@@ -412,7 +416,7 @@
if (currentTime.value == durationTime.value) [_player.currentItem seekToTime:CMTimeMake(0, 1)];
[_player play];
[_playButton setImage:nil forState:UIControlStateNormal];
if (iOS7Later) [UIApplication sharedApplication].statusBarHidden = YES;
[UIApplication sharedApplication].statusBarHidden = YES;
if (self.singleTapGestureBlock) {
self.singleTapGestureBlock();
}
......
......@@ -41,7 +41,7 @@
@property (nonatomic, strong) UIView *cropView;
@property (nonatomic, assign) double progress;
@property (strong, nonatomic) id alertView;
@property (strong, nonatomic) UIAlertController *alertView;
@end
@implementation TZPhotoPreviewController
......@@ -77,8 +77,10 @@
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES animated:YES];
if (iOS7Later) [UIApplication sharedApplication].statusBarHidden = YES;
if (_currentIndex) [_collectionView setContentOffset:CGPointMake((self.view.tz_width + 20) * _currentIndex, 0) animated:NO];
[UIApplication sharedApplication].statusBarHidden = YES;
if (_currentIndex) {
[_collectionView setContentOffset:CGPointMake((self.view.tz_width + 20) * self.currentIndex, 0) animated:NO];
}
[self refreshNaviBarAndBottomBarState];
}
......@@ -86,7 +88,7 @@
[super viewWillDisappear:animated];
[self.navigationController setNavigationBarHidden:NO animated:YES];
TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
if (tzImagePickerVc.needShowStatusBar && iOS7Later) {
if (tzImagePickerVc.needShowStatusBar) {
[UIApplication sharedApplication].statusBarHidden = NO;
}
[TZImageManager manager].shouldFixOrientation = NO;
......@@ -135,7 +137,7 @@
TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
if (_tzImagePickerVc.allowPickingOriginalPhoto) {
_originalPhotoButton = [UIButton buttonWithType:UIButtonTypeCustom];
_originalPhotoButton.imageEdgeInsets = UIEdgeInsetsMake(0, -10, 0, 0);
_originalPhotoButton.imageEdgeInsets = UIEdgeInsetsMake(0, [TZCommonTools isRightToLeftLayout] ? 10 : -10, 0, 0);
_originalPhotoButton.backgroundColor = [UIColor clearColor];
[_originalPhotoButton addTarget:self action:@selector(originalPhotoButtonClick) forControlEvents:UIControlEventTouchUpInside];
_originalPhotoButton.titleLabel.font = [UIFont systemFontOfSize:13];
......@@ -206,7 +208,7 @@
- (void)configCropView {
TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
if (_tzImagePickerVc.maxImagesCount <= 1 && _tzImagePickerVc.allowCrop) {
if (_tzImagePickerVc.maxImagesCount <= 1 && _tzImagePickerVc.allowCrop && _tzImagePickerVc.allowPickingImage) {
[_cropView removeFromSuperview];
[_cropBgView removeFromSuperview];
......@@ -268,7 +270,7 @@
CGFloat toolBarTop = self.view.tz_height - toolBarHeight;
_toolBar.frame = CGRectMake(0, toolBarTop, self.view.tz_width, toolBarHeight);
if (_tzImagePickerVc.allowPickingOriginalPhoto) {
CGFloat fullImageWidth = [_tzImagePickerVc.fullImageBtnTitleStr tz_calculateSizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:13]} maxSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)].width;
CGFloat fullImageWidth = [_tzImagePickerVc.fullImageBtnTitleStr boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:13]} context:nil].size.width;
_originalPhotoButton.frame = CGRectMake(0, 0, fullImageWidth + 56, 44);
_originalPhotoLabel.frame = CGRectMake(fullImageWidth + 42, 0, 80, 44);
}
......@@ -294,7 +296,7 @@
- (void)select:(UIButton *)selectButton {
TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
TZAssetModel *model = _models[_currentIndex];
TZAssetModel *model = _models[self.currentIndex];
if (!selectButton.isSelected) {
// 1. select:check if over the maxImagesCount / 选择照片,检查是否超过了最大个数的限制
if (_tzImagePickerVc.selectedModels.count >= _tzImagePickerVc.maxImagesCount) {
......@@ -305,8 +307,8 @@
} else {
[_tzImagePickerVc addSelectedModel:model];
if (self.photos) {
[_tzImagePickerVc.selectedAssets addObject:_assetsTemp[_currentIndex]];
[self.photos addObject:_photosTemp[_currentIndex]];
[_tzImagePickerVc.selectedAssets addObject:_assetsTemp[self.currentIndex]];
[self.photos addObject:_photosTemp[self.currentIndex]];
}
if (model.type == TZAssetModelMediaTypeVideo && !_tzImagePickerVc.allowPickingMultipleVideo) {
[_tzImagePickerVc showAlertWithTitle:[NSBundle tz_localizedStringForKey:@"Select the video when in multi state, we will handle the video as a photo"]];
......@@ -315,7 +317,7 @@
} else {
NSArray *selectedModels = [NSArray arrayWithArray:_tzImagePickerVc.selectedModels];
for (TZAssetModel *model_item in selectedModels) {
if ([[[TZImageManager manager] getAssetIdentifier:model.asset] isEqualToString:[[TZImageManager manager] getAssetIdentifier:model_item.asset]]) {
if ([model.asset.localIdentifier isEqualToString:model_item.asset.localIdentifier]) {
// 1.6.7版本更新:防止有多个一样的model,一次性被移除了
NSArray *selectedModelsTmp = [NSArray arrayWithArray:_tzImagePickerVc.selectedModels];
for (NSInteger i = 0; i < selectedModelsTmp.count; i++) {
......@@ -331,13 +333,13 @@
NSArray *selectedAssetsTmp = [NSArray arrayWithArray:_tzImagePickerVc.selectedAssets];
for (NSInteger i = 0; i < selectedAssetsTmp.count; i++) {
id asset = selectedAssetsTmp[i];
if ([asset isEqual:_assetsTemp[_currentIndex]]) {
if ([asset isEqual:_assetsTemp[self.currentIndex]]) {
[_tzImagePickerVc.selectedAssets removeObjectAtIndex:i];
break;
}
}
// [_tzImagePickerVc.selectedAssets removeObject:_assetsTemp[_currentIndex]];
[self.photos removeObject:_photosTemp[_currentIndex]];
// [_tzImagePickerVc.selectedAssets removeObject:_assetsTemp[self.currentIndex]];
[self.photos removeObject:_photosTemp[self.currentIndex]];
}
break;
}
......@@ -378,18 +380,22 @@
// 如果没有选中过照片 点击确定时选中当前预览的照片
if (_tzImagePickerVc.selectedModels.count == 0 && _tzImagePickerVc.minImagesCount <= 0) {
TZAssetModel *model = _models[_currentIndex];
TZAssetModel *model = _models[self.currentIndex];
[_tzImagePickerVc addSelectedModel:model];
}
if (_tzImagePickerVc.allowCrop) { // 裁剪状态
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:_currentIndex inSection:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:self.currentIndex inSection:0];
TZPhotoPreviewCell *cell = (TZPhotoPreviewCell *)[_collectionView cellForItemAtIndexPath:indexPath];
if (_tzImagePickerVc.allowCrop && [cell isKindOfClass:[TZPhotoPreviewCell class]]) { // 裁剪状态
_doneButton.enabled = NO;
[_tzImagePickerVc showProgressHUD];
UIImage *cropedImage = [TZImageCropManager cropImageView:cell.previewView.imageView toRect:_tzImagePickerVc.cropRect zoomScale:cell.previewView.scrollView.zoomScale containerView:self.view];
if (_tzImagePickerVc.needCircleCrop) {
cropedImage = [TZImageCropManager circularClipImage:cropedImage];
}
_doneButton.enabled = YES;
[_tzImagePickerVc hideProgressHUD];
if (self.doneButtonClickBlockCropMode) {
TZAssetModel *model = _models[_currentIndex];
TZAssetModel *model = _models[self.currentIndex];
self.doneButtonClickBlockCropMode(cropedImage,model.asset);
}
} else if (self.doneButtonClickBlock) { // 非裁剪状态
......@@ -429,7 +435,6 @@
offSetWidth = offSetWidth + ((self.view.tz_width + 20) * 0.5);
NSInteger currentIndex = offSetWidth / (self.view.tz_width + 20);
if (currentIndex < _models.count && _currentIndex != currentIndex) {
_currentIndex = currentIndex;
[self refreshNaviBarAndBottomBarState];
......@@ -509,12 +514,11 @@
- (void)refreshNaviBarAndBottomBarState {
TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
TZAssetModel *model = _models[_currentIndex];
TZAssetModel *model = _models[self.currentIndex];
_selectButton.selected = model.isSelected;
[self refreshSelectButtonImageViewContentMode];
if (_selectButton.isSelected && _tzImagePickerVc.showSelectedIndex && _tzImagePickerVc.showSelectBtn) {
NSString *assetId = [[TZImageManager manager] getAssetIdentifier:model.asset];
NSString *index = [NSString stringWithFormat:@"%zd", [_tzImagePickerVc.selectedAssetIds indexOfObject:assetId] + 1];
NSString *index = [NSString stringWithFormat:@"%d", (int)([_tzImagePickerVc.selectedAssetIds indexOfObject:model.asset.localIdentifier] + 1)];
_indexLabel.text = index;
_indexLabel.hidden = NO;
} else {
......@@ -564,9 +568,13 @@
}
- (void)showPhotoBytes {
[[TZImageManager manager] getPhotosBytesWithArray:@[_models[_currentIndex]] completion:^(NSString *totalBytes) {
[[TZImageManager manager] getPhotosBytesWithArray:@[_models[self.currentIndex]] completion:^(NSString *totalBytes) {
self->_originalPhotoLabel.text = [NSString stringWithFormat:@"(%@)",totalBytes];
}];
}
- (NSInteger)currentIndex {
return [TZCommonTools isRightToLeftLayout] ? self.models.count - _currentIndex - 1 : _currentIndex;
}
@end
......@@ -49,7 +49,7 @@
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
_originStatusBarStyle = [UIApplication sharedApplication].statusBarStyle;
[UIApplication sharedApplication].statusBarStyle = iOS7Later ? UIStatusBarStyleLightContent : UIStatusBarStyleBlackOpaque;
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
}
- (void)viewWillDisappear:(BOOL)animated {
......@@ -127,6 +127,14 @@
}
}
- (UIStatusBarStyle)preferredStatusBarStyle {
TZImagePickerController *tzImagePicker = (TZImagePickerController *)self.navigationController;
if (tzImagePicker && [tzImagePicker isKindOfClass:[TZImagePickerController class]]) {
return tzImagePicker.statusBarStyle;
}
return [super preferredStatusBarStyle];
}
#pragma mark - Layout
- (void)viewDidLayoutSubviews {
......@@ -157,7 +165,7 @@
[self.navigationController setNavigationBarHidden:YES];
_toolBar.hidden = YES;
[_playButton setImage:nil forState:UIControlStateNormal];
if (iOS7Later) [UIApplication sharedApplication].statusBarHidden = YES;
[UIApplication sharedApplication].statusBarHidden = YES;
} else {
[self pausePlayerAndShowNaviBar];
}
......@@ -198,7 +206,7 @@
[self.navigationController setNavigationBarHidden:NO];
[_playButton setImage:[UIImage imageNamedFromMyBundle:@"MMVideoPreviewPlay"] forState:UIControlStateNormal];
if (self.needShowStatusBar && iOS7Later) {
if (self.needShowStatusBar) {
[UIApplication sharedApplication].statusBarHidden = NO;
}
}
......
{
"name": "react-native-syan-image-picker",
"version": "0.1.7",
"version": "0.1.8",
"description": "React-Native 多图片选择 支持裁剪 压缩",
"main": "index.js",
"scripts": {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment