杨锴
2025-03-11 90dc3329d1973fda691e357cf4523d5c7c67fa1d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
//
//  TZImagePickerController.h
//  TZImagePickerController
//
//  Created by 谭真 on 15/12/24.
//  Copyright © 2015年 谭真. All rights reserved.
//  version 3.8.8 - 2024.10.27
//  更多信息,请前往项目的github地址:https://github.com/banchichen/TZImagePickerController
 
/*
 经过测试,比起xib的方式,把TZAssetCell改用纯代码的方式来写,滑动帧数明显提高了(约提高10帧左右)
 
 最初发现这个问题并修复的是@小鱼周凌宇同学,她的博客地址: http://zhoulingyu.com/
 表示感谢~
 
 原来xib确实会导致性能问题啊...大家也要注意了...
 */
 
#import <UIKit/UIKit.h>
#import "TZAssetModel.h"
#import "NSBundle+TZImagePicker.h"
#import "TZImageManager.h"
#import "TZVideoPlayerController.h"
#import "TZGifPhotoPreviewController.h"
#import "TZPhotoPreviewController.h"
#import "TZPhotoPreviewCell.h"
 
#if __has_include("TZLocationManager.h")
#define TZ_HAVE_LOCATION_CODE   1
#import "TZLocationManager.h"
#else
#undef TZ_HAVE_LOCATION_CODE
#endif
 
#define CURRENT_SYSTEM_VERSION         [[UIDevice currentDevice] systemVersion]
#define SYSTEM_VERSION_GREATER_THAN_15 ([CURRENT_SYSTEM_VERSION floatValue] >= 15.0)
 
@class TZAlbumCell, TZAssetCell;
@protocol TZImagePickerControllerDelegate;
@interface TZImagePickerController : UINavigationController
 
#pragma mark -
/// Use this init method / 用这个初始化方法
- (instancetype)initWithMaxImagesCount:(NSInteger)maxImagesCount delegate:(id<TZImagePickerControllerDelegate>)delegate;
- (instancetype)initWithMaxImagesCount:(NSInteger)maxImagesCount columnNumber:(NSInteger)columnNumber delegate:(id<TZImagePickerControllerDelegate>)delegate;
- (instancetype)initWithMaxImagesCount:(NSInteger)maxImagesCount columnNumber:(NSInteger)columnNumber delegate:(id<TZImagePickerControllerDelegate>)delegate pushPhotoPickerVc:(BOOL)pushPhotoPickerVc;
/// 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:(PHAsset *)asset photo:(UIImage *)photo completion:(void (^)(UIImage *cropImage,PHAsset *asset))completion;
 
#pragma mark -
/// Default is 9 / 默认最大可选9张图片
@property (nonatomic, assign) NSInteger maxImagesCount;
 
/// The minimum count photos user must pick, Default is 0
/// 最小照片必选张数,默认是0
@property (nonatomic, assign) NSInteger minImagesCount;
 
/// If the user does not select any pictures, the current picture is automatically selected when the Finish button is clicked,  Default is YES
/// 如果用户未选择任何图片,在点击完成按钮时自动选中当前图片,默认YES
@property (nonatomic, assign) BOOL autoSelectCurrentWhenDone;
 
/// Always enale the done button, not require minimum 1 photo be picked
/// 让完成按钮一直可以点击,无须最少选择一张图片
@property (nonatomic, assign) BOOL alwaysEnableDoneBtn;
 
/// Sort photos ascending by modificationDate,Default is YES
/// 对照片排序,按修改时间升序,默认是YES。如果设置为NO,最新的照片会显示在最前面,内部的拍照按钮会排在第一个
@property (nonatomic, assign) BOOL sortAscendingByModificationDate;
 
/// The pixel width of output image, Default is 828px,you need to set photoPreviewMaxWidth at the same time
/// 导出图片的宽度,默认828像素宽,你需要同时设置photoPreviewMaxWidth的值
@property (nonatomic, assign) CGFloat photoWidth;
 
/// Default is 600px / 默认600像素宽
@property (nonatomic, assign) CGFloat photoPreviewMaxWidth;
 
/// Default is 30, While fetching photo, HUD will dismiss automatic if timeout;
/// 超时时间,默认为30秒,当取图片时间超过30秒还没有取成功时,会自动dismiss HUD;
@property (nonatomic, assign) NSInteger timeout;
 
/// Default is YES, if set NO, the original photo button will hide. user can't picking original photo.
/// 默认为YES,如果设置为NO,原图按钮将隐藏,用户不能选择发送原图
@property (nonatomic, assign) BOOL allowPickingOriginalPhoto;
 
/// Default is YES, if set NO, user can't picking video.
/// 默认为YES,如果设置为NO,用户将不能选择视频
@property (nonatomic, assign) BOOL allowPickingVideo;
 
/// Default is NO, if set YES, user can edit video.
/// 默认为NO,如果设置为YES, 用户能编辑视频
@property (nonatomic, assign) BOOL allowEditVideo;
 
/// Export quality of cropped video, Default is AVAssetExportPresetMediumQuality
/// 裁剪视频的导出质量,默认是 AVAssetExportPresetMediumQuality
@property (nonatomic, copy) NSString *presetName;
 
/// Default is 30s. If it exceeds the video duration, it is the video duration.The minimum duration of video crop is 1s.
/// 默认是30s,如果超过视频时长,则为视频时长,小于1s不裁剪
@property (nonatomic, assign) NSInteger maxCropVideoDuration;
 
/// Default is NO, if set YES, The edited video will be automatically saved to the album.
/// 默认为NO,如果设置为YES,编辑后的视频会自动保存到相册
@property (nonatomic, assign) BOOL saveEditedVideoToAlbum;
 
/// Default is NO / 默认为NO,为YES时可以多选视频/gif/图片,和照片共享最大可选张数maxImagesCount的限制
@property (nonatomic, assign) BOOL allowPickingMultipleVideo;
 
/// Default is NO, if set YES, user can picking gif image. When NO, gif will be treated as a regular image. If want not displayed, please refer to isAssetCanBeDisplayed
/// 默认为NO,如果设置为YES,用户可以选择gif图片。为NO时gif会被当成普通图片,若要不显示,请参考isAssetCanBeDisplayed
@property (nonatomic, assign) BOOL allowPickingGif;
 
/// Default is YES, if set NO, user can't picking image.
/// 默认为YES,如果设置为NO,用户将不能选择发送图片
@property (nonatomic, assign) BOOL allowPickingImage;
 
/// Default is YES, if set NO, user can't take picture.
/// 默认为YES,如果设置为NO, 用户将不能拍摄照片
@property (nonatomic, assign) BOOL allowTakePicture;
 
#ifdef TZ_HAVE_LOCATION_CODE
@property (nonatomic, assign) BOOL allowCameraLocation;
#endif
 
/// Default is YES, if set NO, user can't take video.
/// 默认为YES,如果设置为NO, 用户将不能拍摄视频
@property(nonatomic, assign) BOOL allowTakeVideo;
/// Default value is 10 minutes / 视频最大拍摄时间,默认是10分钟,单位是秒
@property (assign, nonatomic) NSTimeInterval videoMaximumDuration;
/// Customizing UIImagePickerController's other properties, such as videoQuality / 定制UIImagePickerController的其它属性,比如视频拍摄质量videoQuality
@property (nonatomic, copy) void(^uiImagePickerControllerSettingBlock)(UIImagePickerController *imagePickerController);
 
/// 首选语言,如果设置了就用该语言,不设则取当前系统语言。
/// 支持zh-Hans、zh-Hant、en、vi等值,详见TZImagePickerController.bundle内的语言资源
@property (copy, nonatomic) NSString *preferredLanguage;
 
/// 语言bundle,preferredLanguage变化时languageBundle会变化
/// 可通过手动设置bundle,让选择器支持新的的语言(需要在设置preferredLanguage后设置languageBundle)。欢迎提交PR把语言文件提交上来~
@property (strong, nonatomic) NSBundle *languageBundle;
 
/// Default is YES, if set NO, user can't preview photo.
/// 默认为YES,如果设置为NO,预览按钮将隐藏,用户将不能去预览照片
@property (nonatomic, assign) BOOL allowPreview;
 
/// Default is YES, if set NO, the picker don't dismiss itself.
/// 默认为YES,如果设置为NO, 选择器将不会自己dismiss
@property(nonatomic, assign) BOOL autoDismiss;
 
/// Default is NO, if set YES, in the delegate method the photos and infos will be nil, only assets hava value.
/// 默认为NO,如果设置为YES,代理方法里photos和infos会是nil,只返回assets
@property (assign, nonatomic) BOOL onlyReturnAsset;
 
/// Default is NO, if set YES, will show the image's selected index.
/// 默认为NO,如果设置为YES,会显示照片的选中序号
@property (assign, nonatomic) BOOL showSelectedIndex;
 
/// Default is NO, if set YES, when selected photos's count up to maxImagesCount, other photo will show float layer what's color is cannotSelectLayerColor.
/// 默认是NO,如果设置为YES,当照片选择张数达到maxImagesCount时,其它照片会显示颜色为cannotSelectLayerColor的浮层
@property (assign, nonatomic) BOOL showPhotoCannotSelectLayer;
/// Default is white color with 0.8 alpha;
@property (strong, nonatomic) UIColor *cannotSelectLayerColor;
 
/// Default is YES, if set NO, the result photo will be scaled to photoWidth pixel width. The photoWidth default is 828px
/// 默认是YES,如果设置为NO,内部会缩放图片到photoWidth像素宽
@property (assign, nonatomic) BOOL notScaleImage;
 
/// 默认是NO,如果设置为YES,导出视频时会修正转向(慎重设为YES,可能导致部分安卓下拍的视频导出失败)
@property (assign, nonatomic) BOOL needFixComposition;
 
/// The photos user have selected
/// 用户选中过的图片数组
@property (nonatomic, strong) NSMutableArray *selectedAssets;
@property (nonatomic, strong) NSMutableArray<TZAssetModel *> *selectedModels;
@property (nonatomic, strong) NSMutableArray *selectedAssetIds;
- (void)addSelectedModel:(TZAssetModel *)model;
- (void)removeSelectedModel:(TZAssetModel *)model;
 
/// Minimum selectable photo width, Default is 0
/// 最小可选中的图片宽度,默认是0,小于这个宽度的图片不可选中
@property (nonatomic, assign) NSInteger minPhotoWidthSelectable;
@property (nonatomic, assign) NSInteger minPhotoHeightSelectable;
/// Hide the photo what can not be selected, Default is NO
/// 隐藏不可以选中的图片,默认是NO,不推荐将其设置为YES
@property (nonatomic, assign) BOOL hideWhenCanNotSelect;
/// Deprecated, Use statusBarStyle (顶部statusBar 是否为系统默认的黑色,默认为NO)
@property (nonatomic, assign) BOOL isStatusBarDefault __attribute__((deprecated("Use -statusBarStyle.")));
/// statusBar的样式,默认为UIStatusBarStyleLightContent
@property (assign, nonatomic) UIStatusBarStyle statusBarStyle;
 
#pragma mark -
/// Single selection mode, valid when maxImagesCount = 1
/// 单选模式,maxImagesCount为1时才生效
@property (nonatomic, assign) BOOL showSelectBtn;        ///< 在单选模式下,照片列表页中,显示选择按钮,默认为NO
@property (nonatomic, assign) BOOL allowCrop;            ///< 允许裁剪,默认为YES,showSelectBtn为NO才生效
@property (nonatomic, assign) BOOL scaleAspectFillCrop;  ///< 是否图片等比缩放填充cropRect区域,开启后预览页面无法左右滑动切换图片
@property (nonatomic, assign) CGRect cropRect;           ///< 裁剪框的尺寸
@property (nonatomic, assign) CGRect cropRectPortrait;   ///< 裁剪框的尺寸(竖屏)
@property (nonatomic, assign) CGRect cropRectLandscape;  ///< 裁剪框的尺寸(横屏)
@property (nonatomic, assign) BOOL needCircleCrop;       ///< 需要圆形裁剪框
@property (nonatomic, assign) NSInteger circleCropRadius;  ///< 圆形裁剪框半径大小
@property (nonatomic, copy) void (^cropViewSettingBlock)(UIView *cropView);     ///< 自定义裁剪框的其他属性
@property (nonatomic, copy) void (^navLeftBarButtonSettingBlock)(UIButton *leftButton);     ///< 自定义返回按钮样式及其属性
 
/// 【自定义各页面/组件的样式】在界面初始化/组件setModel完成后调用,允许外界修改样式等
@property (nonatomic, copy) void (^photoPickerPageUIConfigBlock)(UICollectionView *collectionView, UIView *bottomToolBar, UIButton *previewButton, UIButton *originalPhotoButton, UILabel *originalPhotoLabel, UIButton *doneButton, UIImageView *numberImageView, UILabel *numberLabel, UIView *divideLine);
@property (nonatomic, copy) void (^photoPreviewPageUIConfigBlock)(UICollectionView *collectionView, UIView *naviBar, UIButton *backButton, UIButton *selectButton, UILabel *indexLabel, UIView *toolBar, UIButton *originalPhotoButton, UILabel *originalPhotoLabel, UIButton *doneButton, UIImageView *numberImageView, UILabel *numberLabel);
@property (nonatomic, copy) void (^videoPreviewPageUIConfigBlock)(UIButton *playButton, UIView *toolBar, UIButton *editBtn, UIButton *doneButton);
@property (nonatomic, copy) void (^videoEditViewPageUIConfigBlock)(UIButton *playButton,UILabel *cropVideoDurationLabel, UIButton *editButton, UIButton *doneButton);
@property (nonatomic, copy) void (^gifPreviewPageUIConfigBlock)(UIView *toolBar, UIButton *doneButton);
@property (nonatomic, copy) void (^albumPickerPageUIConfigBlock)(UITableView *tableView);
@property (nonatomic, copy) void (^assetCellDidSetModelBlock)(TZAssetCell *cell, UIImageView *imageView, UIImageView *selectImageView, UILabel *indexLabel, UIView *bottomView, UILabel *timeLength, UIImageView *videoImgView);
@property (nonatomic, copy) void (^albumCellDidSetModelBlock)(TZAlbumCell *cell, UIImageView *posterImageView, UILabel *titleLabel);
/// 【自定义各页面/组件的frame】在界面viewDidLayoutSubviews/组件layoutSubviews后调用,允许外界修改frame等
@property (nonatomic, copy) void (^photoPickerPageDidLayoutSubviewsBlock)(UICollectionView *collectionView, UIView *bottomToolBar, UIButton *previewButton, UIButton *originalPhotoButton, UILabel *originalPhotoLabel, UIButton *doneButton, UIImageView *numberImageView, UILabel *numberLabel, UIView *divideLine);
@property (nonatomic, copy) void (^photoPreviewPageDidLayoutSubviewsBlock)(UICollectionView *collectionView, UIView *naviBar, UIButton *backButton, UIButton *selectButton, UILabel *indexLabel, UIView *toolBar, UIButton *originalPhotoButton, UILabel *originalPhotoLabel, UIButton *doneButton, UIImageView *numberImageView, UILabel *numberLabel);
@property (nonatomic, copy) void (^videoPreviewPageDidLayoutSubviewsBlock)(UIButton *playButton, UIView *toolBar, UIButton *editButton, UIButton *doneButton);
@property (nonatomic, copy) void (^videoEditViewPageDidLayoutSubviewsBlock)(UIButton *playButton, UILabel *cropVideoDurationLabel, UIButton *cancelButton, UIButton *doneButton);
@property (nonatomic, copy) void (^gifPreviewPageDidLayoutSubviewsBlock)(UIView *toolBar, UIButton *doneButton);
@property (nonatomic, copy) void (^albumPickerPageDidLayoutSubviewsBlock)(UITableView *tableView);
@property (nonatomic, copy) void (^assetCellDidLayoutSubviewsBlock)(TZAssetCell *cell, UIImageView *imageView, UIImageView *selectImageView, UILabel *indexLabel, UIView *bottomView, UILabel *timeLength, UIImageView *videoImgView);
@property (nonatomic, copy) void (^albumCellDidLayoutSubviewsBlock)(TZAlbumCell *cell, UIImageView *posterImageView, UILabel *titleLabel);
/// 自定义各页面/组件的frame】刷新底部状态(refreshNaviBarAndBottomBarState)使用的
@property (nonatomic, copy) void (^photoPickerPageDidRefreshStateBlock)(UICollectionView *collectionView, UIView *bottomToolBar, UIButton *previewButton, UIButton *originalPhotoButton, UILabel *originalPhotoLabel, UIButton *doneButton, UIImageView *numberImageView, UILabel *numberLabel, UIView *divideLine);
 
@property (nonatomic, copy) void (^photoPreviewPageDidRefreshStateBlock)(UICollectionView *collectionView, UIView *naviBar, UIButton *backButton, UIButton *selectButton, UILabel *indexLabel, UIView *toolBar, UIButton *originalPhotoButton, UILabel *originalPhotoLabel, UIButton *doneButton, UIImageView *numberImageView, UILabel *numberLabel);
 
#pragma mark -
- (UIAlertController *)showAlertWithTitle:(NSString *)title;
- (void)showProgressHUD;
- (void)hideProgressHUD;
@property (nonatomic, assign) BOOL isSelectOriginalPhoto;
@property (assign, nonatomic) BOOL needShowStatusBar;
 
#pragma mark -
@property (nonatomic, copy) NSString *takePictureImageName __attribute__((deprecated("Use -takePictureImage.")));
@property (nonatomic, copy) NSString *photoSelImageName __attribute__((deprecated("Use -photoSelImage.")));
@property (nonatomic, copy) NSString *photoDefImageName __attribute__((deprecated("Use -photoDefImage.")));
@property (nonatomic, copy) NSString *photoOriginSelImageName __attribute__((deprecated("Use -photoOriginSelImage.")));
@property (nonatomic, copy) NSString *photoOriginDefImageName __attribute__((deprecated("Use -photoOriginDefImage.")));
@property (nonatomic, copy) NSString *photoPreviewOriginDefImageName __attribute__((deprecated("Use -photoPreviewOriginDefImage.")));
@property (nonatomic, copy) NSString *photoNumberIconImageName __attribute__((deprecated("Use -photoNumberIconImage.")));
@property (nonatomic, strong) UIImage *takePictureImage;
@property (nonatomic, strong) UIImage *addMorePhotoImage;
@property (nonatomic, strong) UIImage *photoSelImage;
@property (nonatomic, strong) UIImage *photoDefImage;
@property (nonatomic, strong) UIImage *photoOriginSelImage;
@property (nonatomic, strong) UIImage *photoOriginDefImage;
@property (nonatomic, strong) UIImage *photoPreviewOriginDefImage;
@property (nonatomic, strong) UIImage *photoNumberIconImage;
 
#pragma mark -
/// Appearance / 外观颜色 + 按钮文字
@property (nonatomic, strong) UIColor *oKButtonTitleColorNormal;
@property (nonatomic, strong) UIColor *oKButtonTitleColorDisabled;
@property (nonatomic, strong) UIColor *naviBgColor;
@property (nonatomic, strong) UIColor *naviTitleColor;
@property (nonatomic, strong) UIFont *naviTitleFont;
@property (nonatomic, strong) UIColor *barItemTextColor;
@property (nonatomic, strong) UIFont *barItemTextFont;
 
@property (nonatomic, copy) NSString *doneBtnTitleStr;
@property (nonatomic, copy) NSString *cancelBtnTitleStr;
@property (nonatomic, copy) NSString *previewBtnTitleStr;
@property (nonatomic, copy) NSString *fullImageBtnTitleStr;
@property (nonatomic, copy) NSString *settingBtnTitleStr;
@property (nonatomic, copy) NSString *processHintStr;
@property (nonatomic, copy) NSString *editBtnTitleStr;
@property (nonatomic, copy) NSString *editViewCancelBtnTitleStr;
 
/// Icon theme color, default is green color like wechat, the value is r:31 g:185 b:34. Currently only support image selection icon when showSelectedIndex is YES. If you need it, please set it as soon as possible
/// icon主题色,默认是微信的绿色,值是r:31 g:185 b:34。目前仅支持showSelectedIndex为YES时的图片选中icon。如需要,请尽早设置它。
@property (strong, nonatomic) UIColor *iconThemeColor;
 
#pragma mark -
- (void)cancelButtonClick;
 
// For method annotations, see the corresponding method in TZImagePickerControllerDelegate / 方法注释见TZImagePickerControllerDelegate中对应方法
@property (nonatomic, copy) void (^didFinishPickingPhotosHandle)(NSArray<UIImage *> *photos,NSArray *assets,BOOL isSelectOriginalPhoto);
@property (nonatomic, copy) void (^didFinishPickingPhotosWithInfosHandle)(NSArray<UIImage *> *photos,NSArray *assets,BOOL isSelectOriginalPhoto,NSArray<NSDictionary *> *infos);
@property (nonatomic, copy) void (^imagePickerControllerDidCancelHandle)(void);
@property (nonatomic, copy) void (^didFinishPickingVideoHandle)(UIImage *coverImage,PHAsset *asset);
@property (nonatomic, copy) void (^didFinishPickingAndEditingVideoHandle)(UIImage *coverImage,NSString *outputPath,NSString *errorMsg);
@property (nonatomic, copy) void (^didFinishPickingGifImageHandle)(UIImage *animatedImage,id sourceAssets);
 
@property (nonatomic, weak) id<TZImagePickerControllerDelegate> pickerDelegate;
 
@end
 
 
@protocol TZImagePickerControllerDelegate <NSObject>
@optional
// The picker should dismiss itself; when it dismissed these callback will be called.
// You can also set autoDismiss to NO, then the picker don't dismiss itself.
// If isOriginalPhoto is YES, user picked the original photo.
// You can get original photo with asset, by the method [[TZImageManager manager] getOriginalPhotoWithAsset:completion:].
// The UIImage Object in photos default width is 828px, you can set it by photoWidth property.
// 这个照片选择器会自己dismiss,当选择器dismiss的时候,会执行下面的代理方法
// 你也可以设置autoDismiss属性为NO,选择器就不会自己dismis了
// 如果isSelectOriginalPhoto为YES,表明用户选择了原图
// 你可以通过一个asset获得原图,通过这个方法:[[TZImageManager manager] getOriginalPhotoWithAsset:completion:]
// photos数组里的UIImage对象,默认是828像素宽,你可以通过设置photoWidth属性的值来改变它
- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingPhotos:(NSArray<UIImage *> *)photos sourceAssets:(NSArray *)assets isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto;
- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingPhotos:(NSArray<UIImage *> *)photos sourceAssets:(NSArray *)assets isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto infos:(NSArray<NSDictionary *> *)infos;
- (void)tz_imagePickerControllerDidCancel:(TZImagePickerController *)picker;
 
/// 如果用户选择了某张照片下面的代理方法会被执行
/// 如果isSelectOriginalPhoto为YES,表明用户选择了原图
/// 你可以通过一个asset获得原图,通过这个方法:[[TZImageManager manager] getOriginalPhotoWithAsset:completion:]
- (void)imagePickerController:(TZImagePickerController *)picker didSelectAsset:(PHAsset *)asset photo:(UIImage *)photo isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto;
 
/// 如果用户取消选择了某张照片下面的代理方法会被执行
/// 如果isSelectOriginalPhoto为YES,表明用户选择了原图
/// 你可以通过一个asset获得原图,通过这个方法:[[TZImageManager manager] getOriginalPhotoWithAsset:completion:]
- (void)imagePickerController:(TZImagePickerController *)picker didDeselectAsset:(PHAsset *)asset photo:(UIImage *)photo isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto;
 
// If user picking a video and allowPickingMultipleVideo is NO, this callback will be called.
// If allowPickingMultipleVideo is YES, will call imagePickerController:didFinishPickingPhotos:sourceAssets:isSelectOriginalPhoto:
// 如果用户选择了一个视频且allowPickingMultipleVideo是NO,下面的代理方法会被执行
// 如果allowPickingMultipleVideo是YES,将会调用imagePickerController:didFinishPickingPhotos:sourceAssets:isSelectOriginalPhoto:
- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingVideo:(UIImage *)coverImage sourceAssets:(PHAsset *)asset;
 
// If allowEditVideo is YES and allowPickingMultipleVideo is NO, When user picking a video, this callback will be called.
// If allowPickingMultipleVideo is YES, video editing is not supported, will call imagePickerController:didFinishPickingPhotos:sourceAssets:isSelectOriginalPhoto:
// 当allowEditVideo是YES且allowPickingMultipleVideo是NO是,如果用户选择了一个视频,下面的代理方法会被执行
// 如果allowPickingMultipleVideo是YES,则不支持编辑视频,将会调用imagePickerController:didFinishPickingPhotos:sourceAssets:isSelectOriginalPhoto:
- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingAndEditingVideo:(UIImage *)coverImage outputPath:(NSString *)outputPath error:(NSString *)errorMsg;
 
// When saving the edited video to the album fails, this callback will be called.
// 编辑后的视频自动保存到相册失败时,下面的代理方法会被执行
- (void)imagePickerController:(TZImagePickerController *)picker didFailToSaveEditedVideoWithError:(NSError *)error;
 
// If user picking a gif image and allowPickingMultipleVideo is NO, this callback will be called.
// If allowPickingMultipleVideo is YES, will call imagePickerController:didFinishPickingPhotos:sourceAssets:isSelectOriginalPhoto:
// 如果用户选择了一个gif图片且allowPickingMultipleVideo是NO,下面的代理方法会被执行
// 如果allowPickingMultipleVideo是YES,将会调用imagePickerController:didFinishPickingPhotos:sourceAssets:isSelectOriginalPhoto:
- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingGifImage:(UIImage *)animatedImage sourceAssets:(PHAsset *)asset;
 
// Decide album show or not't
// 决定相册显示与否 albumName:相册名字 result:相册原始数据
- (BOOL)isAlbumCanSelect:(NSString *)albumName result:(PHFetchResult *)result;
 
// Decide asset show or not't
// 决定照片显示与否
- (BOOL)isAssetCanSelect:(PHAsset *)asset __attribute__((deprecated("Use -isAssetCanBeDisplayed:.")));
- (BOOL)isAssetCanBeDisplayed:(PHAsset *)asset;
 
// Decide asset can be selected
// 决定照片能否被选中
- (BOOL)isAssetCanBeSelected:(PHAsset *)asset;
@end
 
 
@interface TZAlbumPickerController : UIViewController
@property (nonatomic, assign) NSInteger columnNumber;
@property (assign, nonatomic) BOOL isFirstAppear;
- (void)configTableView;
@end
 
 
@interface UIImage (MyBundle)
+ (UIImage *)tz_imageNamedFromMyBundle:(NSString *)name;
@end
 
 
@interface TZCommonTools : NSObject
+ (UIEdgeInsets)tz_safeAreaInsets;
+ (BOOL)tz_isIPhoneX;
+ (BOOL)tz_isLandscape;
+ (CGFloat)tz_statusBarHeight;
// 获得Info.plist数据字典
+ (NSDictionary *)tz_getInfoDictionary;
+ (NSString *)tz_getAppName;
+ (BOOL)tz_isRightToLeftLayout;
+ (void)configBarButtonItem:(UIBarButtonItem *)item tzImagePickerVc:(TZImagePickerController *)tzImagePickerVc;
+ (BOOL)isICloudSyncError:(NSError *)error;
+ (BOOL)isAssetNotSelectable:(TZAssetModel *)model tzImagePickerVc:(TZImagePickerController *)tzImagePickerVc;
@end
 
 
@interface TZImagePickerConfig : NSObject
+ (instancetype)sharedInstance;
@property (copy, nonatomic) NSString *preferredLanguage;
@property(nonatomic, assign) BOOL allowPickingImage;
@property (nonatomic, assign) BOOL allowPickingVideo;
@property (strong, nonatomic) NSBundle *languageBundle;
@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