HXCustomNavigationController.m 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. //
  2. // HXCustomNavigationController.m
  3. // HXPhotoPickerExample
  4. //
  5. // Created by Silence on 2017/10/31.
  6. // Copyright © 2017年 Silence. All rights reserved.
  7. //
  8. #import "HXCustomNavigationController.h"
  9. #import "HXAlbumListViewController.h"
  10. #import "HXPhotoViewController.h"
  11. #import "HXPhotoTools.h"
  12. #import "HXAssetManager.h"
  13. @interface HXCustomNavigationController ()<HXAlbumListViewControllerDelegate, HXPhotoViewControllerDelegate>
  14. @property (assign, nonatomic) BOOL didPresentImagePicker;
  15. @property (assign, nonatomic) BOOL initialAuthorization;
  16. @property (strong, nonatomic) NSTimer *timer;
  17. @property (weak, nonatomic) UIImageView *imageView;
  18. @property (assign, nonatomic) PHImageRequestID requestID;
  19. @end
  20. @implementation HXCustomNavigationController
  21. - (instancetype)initWithManager:(HXPhotoManager *)manager {
  22. return [self initWithManager:manager delegate:nil doneBlock:nil cancelBlock:nil];
  23. }
  24. - (instancetype)initWithManager:(HXPhotoManager *)manager
  25. delegate:(id<HXCustomNavigationControllerDelegate>)delegate {
  26. return [self initWithManager:manager delegate:delegate doneBlock:nil cancelBlock:nil];
  27. }
  28. - (instancetype)initWithManager:(HXPhotoManager *)manager
  29. doneBlock:(viewControllerDidDoneBlock)doneBlock
  30. cancelBlock:(viewControllerDidCancelBlock)cancelBlock {
  31. return [self initWithManager:manager delegate:nil doneBlock:doneBlock cancelBlock:cancelBlock];
  32. }
  33. - (instancetype)initWithManager:(HXPhotoManager *)manager
  34. delegate:(id<HXCustomNavigationControllerDelegate>)delegate
  35. doneBlock:(viewControllerDidDoneBlock)doneBlock
  36. cancelBlock:(viewControllerDidCancelBlock)cancelBlock {
  37. [manager selectedListTransformBefore];
  38. manager.selectPhotoing = YES;
  39. if (manager.configuration.albumShowMode == HXPhotoAlbumShowModeDefault) {
  40. HXAlbumListViewController *vc = [[HXAlbumListViewController alloc] initWithManager:manager];
  41. self = [super initWithRootViewController:vc];
  42. self.modalPresentationStyle = UIModalPresentationOverFullScreen;
  43. self.modalPresentationCapturesStatusBarAppearance = YES;
  44. if (self) {
  45. self.hx_delegate = delegate;
  46. self.manager = manager;
  47. [self requestAuthorization];
  48. self.doneBlock = doneBlock;
  49. self.cancelBlock = cancelBlock;
  50. vc.doneBlock = self.doneBlock;
  51. vc.cancelBlock = self.cancelBlock;
  52. vc.delegate = self;
  53. }
  54. }else if (manager.configuration.albumShowMode == HXPhotoAlbumShowModePopup) {
  55. HXPhotoViewController *vc = [[HXPhotoViewController alloc] init];
  56. vc.manager = manager;
  57. self = [super initWithRootViewController:vc];
  58. self.modalPresentationStyle = UIModalPresentationOverFullScreen;
  59. self.modalPresentationCapturesStatusBarAppearance = YES;
  60. if (self) {
  61. self.hx_delegate = delegate;
  62. self.manager = manager;
  63. [self requestAuthorization];
  64. self.doneBlock = doneBlock;
  65. self.cancelBlock = cancelBlock;
  66. vc.doneBlock = self.doneBlock;
  67. vc.cancelBlock = self.cancelBlock;
  68. vc.delegate = self;
  69. }
  70. }
  71. return self;
  72. }
  73. - (void)requestAuthorization {
  74. self.initialAuthorization = NO;
  75. HXWeakSelf
  76. #ifdef __IPHONE_14_0
  77. if (@available(iOS 14, *)) {
  78. [HXPhotoCommon photoCommon].photoLibraryDidChange = ^{
  79. if (!weakSelf.initialAuthorization) {
  80. if (weakSelf.timer) {
  81. [weakSelf.timer invalidate];
  82. weakSelf.timer = nil;
  83. }
  84. [weakSelf imagePickerDidFinish];
  85. }
  86. };
  87. }
  88. #endif
  89. PHAuthorizationStatus status = [HXPhotoTools authorizationStatus];
  90. if (status == PHAuthorizationStatusAuthorized) {
  91. [self requestModel];
  92. return;
  93. }
  94. #ifdef __IPHONE_14_0
  95. else if (@available(iOS 14, *)) {
  96. if (status == PHAuthorizationStatusLimited) {
  97. [self requestModel];
  98. return;
  99. }
  100. }
  101. #endif
  102. if (status == PHAuthorizationStatusNotDetermined) {
  103. self.initialAuthorization = YES;
  104. }
  105. [HXPhotoTools requestAuthorization:nil handler:^(PHAuthorizationStatus status) {
  106. if (status == PHAuthorizationStatusAuthorized) {
  107. [self requestModel];
  108. if (self.reloadAsset) {
  109. self.reloadAsset(self.initialAuthorization);
  110. }
  111. }
  112. #ifdef __IPHONE_14_0
  113. else if (@available(iOS 14, *)) {
  114. if (status == PHAuthorizationStatusLimited) {
  115. self.didPresentImagePicker = YES;
  116. }
  117. #endif
  118. else if (status == PHAuthorizationStatusRestricted ||
  119. status == PHAuthorizationStatusDenied) {
  120. if (self.reloadAsset) {
  121. self.reloadAsset(weakSelf.initialAuthorization);
  122. }
  123. }
  124. #ifdef __IPHONE_14_0
  125. }else if (status == PHAuthorizationStatusRestricted ||
  126. status == PHAuthorizationStatusDenied) {
  127. if (self.reloadAsset) {
  128. self.reloadAsset(self.initialAuthorization);
  129. }
  130. }
  131. #endif
  132. }];
  133. }
  134. - (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {
  135. if (!self.initialAuthorization) {
  136. [super presentViewController:viewControllerToPresent animated:flag completion:completion];
  137. return;
  138. }
  139. #ifdef __IPHONE_14_0
  140. if (@available(iOS 14, *)) {
  141. if ([viewControllerToPresent isKindOfClass:[UIImagePickerController class]]) {
  142. UIImagePickerController *imagePickerController = (UIImagePickerController *)viewControllerToPresent;
  143. if (imagePickerController.sourceType == UIImagePickerControllerSourceTypePhotoLibrary) {
  144. HXWeakSelf
  145. self.timer = [NSTimer scheduledTimerWithTimeInterval:0.5 repeats:YES block:^(NSTimer * _Nonnull timer) {
  146. if ([weakSelf.presentedViewController isKindOfClass:[UIImagePickerController class]]) {
  147. weakSelf.didPresentImagePicker = YES;
  148. }else {
  149. if (weakSelf.didPresentImagePicker) {
  150. weakSelf.didPresentImagePicker = NO;
  151. [timer invalidate];
  152. weakSelf.timer = nil;
  153. [weakSelf imagePickerDidFinish];
  154. }
  155. }
  156. }];
  157. }
  158. }
  159. }
  160. #endif
  161. [super presentViewController:viewControllerToPresent animated:flag completion:completion];
  162. }
  163. - (void)imagePickerDidFinish {
  164. [HXPhotoCommon photoCommon].cameraRollLocalIdentifier = nil;
  165. [HXPhotoCommon photoCommon].cameraRollResult = nil;
  166. self.cameraRollAlbumModel = nil;
  167. self.albums = nil;
  168. [self requestModel];
  169. if (self.reloadAsset) {
  170. self.reloadAsset(self.initialAuthorization);
  171. }
  172. if (self.initialAuthorization) {
  173. [[NSNotificationCenter defaultCenter] postNotificationName:@"HXPhotoRequestAuthorizationCompletion" object:nil];
  174. self.initialAuthorization = NO;
  175. }
  176. }
  177. - (void)requestModel {
  178. [self.view hx_showLoadingHUDText:nil];
  179. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  180. HXWeakSelf
  181. [self.manager getCameraRollAlbumCompletion:^(HXAlbumModel *albumModel) {
  182. weakSelf.cameraRollAlbumModel = albumModel;
  183. dispatch_async(dispatch_get_main_queue(), ^{
  184. if (weakSelf.requestCameraRollCompletion) {
  185. weakSelf.requestCameraRollCompletion();
  186. }
  187. });
  188. }];
  189. [self.manager getAllAlbumModelWithCompletion:^(NSMutableArray<HXAlbumModel *> *albums) {
  190. weakSelf.albums = albums.mutableCopy;
  191. dispatch_async(dispatch_get_main_queue(), ^{
  192. if (weakSelf.requestAllAlbumCompletion) {
  193. weakSelf.requestAllAlbumCompletion();
  194. }
  195. });
  196. }];
  197. });
  198. }
  199. - (void)viewWillAppear:(BOOL)animated {
  200. [super viewWillAppear:animated];
  201. if (self.manager.viewWillAppear) {
  202. self.manager.viewWillAppear(self);
  203. }
  204. }
  205. - (void)viewDidAppear:(BOOL)animated {
  206. [super viewDidAppear:animated];
  207. if (self.manager.viewDidAppear) {
  208. self.manager.viewDidAppear(self);
  209. }
  210. }
  211. - (void)viewWillDisappear:(BOOL)animated {
  212. [super viewWillDisappear:animated];
  213. if (_timer) {
  214. self.didPresentImagePicker = NO;
  215. [self.timer invalidate];
  216. self.timer = nil;
  217. }
  218. if (self.manager.viewWillDisappear) {
  219. self.manager.viewWillDisappear(self);
  220. }
  221. }
  222. - (void)viewDidDisappear:(BOOL)animated {
  223. [super viewDidDisappear:animated];
  224. if (self.manager.viewDidDisappear) {
  225. self.manager.viewDidDisappear(self);
  226. }
  227. }
  228. - (void)viewDidLoad {
  229. [super viewDidLoad];
  230. // Do any additional setup after loading the view.
  231. if ([HXPhotoCommon photoCommon].clearAssetRequestID) {
  232. [[PHImageManager defaultManager] cancelImageRequest:[HXPhotoCommon photoCommon].clearAssetRequestID];
  233. [HXPhotoCommon photoCommon].clearAssetRequestID = -1;
  234. }
  235. }
  236. #pragma mark - < HXAlbumListViewControllerDelegate >
  237. - (void)albumListViewControllerCancelDismissCompletion:(HXAlbumListViewController *)albumListViewController {
  238. if ([self.hx_delegate respondsToSelector:@selector(photoNavigationViewControllerCancelDismissCompletion:)]) {
  239. [self.hx_delegate photoNavigationViewControllerCancelDismissCompletion:self];
  240. }
  241. }
  242. - (void)albumListViewControllerDidCancel:(HXAlbumListViewController *)albumListViewController {
  243. [self clearAssetCacheWithAddOnWindow:!self.manager.selectPhotoCancelDismissAnimated];
  244. if ([self.hx_delegate respondsToSelector:@selector(photoNavigationViewControllerDidCancel:)]) {
  245. [self.hx_delegate photoNavigationViewControllerDidCancel:self];
  246. }
  247. }
  248. - (void)albumListViewController:(HXAlbumListViewController *)albumListViewController didDoneAllList:(NSArray<HXPhotoModel *> *)allList photos:(NSArray<HXPhotoModel *> *)photoList videos:(NSArray<HXPhotoModel *> *)videoList original:(BOOL)original {
  249. if (!self.manager.configuration.requestImageAfterFinishingSelection) {
  250. [self clearAssetCacheWithAddOnWindow:!self.manager.selectPhotoFinishDismissAnimated];
  251. }
  252. if ([self.hx_delegate respondsToSelector:@selector(photoNavigationViewController:didDoneAllList:photos:videos:original:)]) {
  253. [self.hx_delegate photoNavigationViewController:self didDoneAllList:allList photos:photoList videos:videoList original:original];
  254. }
  255. }
  256. - (void)albumListViewController:(HXAlbumListViewController *)albumListViewController didDoneWithResult:(HXPickerResult *)result {
  257. if ([self.hx_delegate respondsToSelector:@selector(photoNavigationViewController:didDoneWithResult:)]) {
  258. [self.hx_delegate photoNavigationViewController:self didDoneWithResult:result];
  259. }
  260. }
  261. #pragma mark - < HXPhotoViewControllerDelegate >
  262. - (void)photoViewControllerFinishDismissCompletion:(HXPhotoViewController *)photoViewController {
  263. if ([self.hx_delegate respondsToSelector:@selector(photoNavigationViewControllerFinishDismissCompletion:)]) {
  264. [self.hx_delegate photoNavigationViewControllerFinishDismissCompletion:self];
  265. }
  266. }
  267. - (void)photoViewController:(HXPhotoViewController *)photoViewController didDoneWithResult:(HXPickerResult *)result {
  268. if ([self.hx_delegate respondsToSelector:@selector(photoNavigationViewController:didDoneWithResult:)]) {
  269. [self.hx_delegate photoNavigationViewController:self didDoneWithResult:result];
  270. }
  271. }
  272. - (void)photoViewControllerCancelDismissCompletion:(HXPhotoViewController *)photoViewController {
  273. if ([self.hx_delegate respondsToSelector:@selector(photoNavigationViewControllerCancelDismissCompletion:)]) {
  274. [self.hx_delegate photoNavigationViewControllerCancelDismissCompletion:self];
  275. }
  276. }
  277. - (void)photoViewControllerDidCancel:(HXPhotoViewController *)photoViewController {
  278. [self clearAssetCacheWithAddOnWindow:!self.manager.selectPhotoCancelDismissAnimated];
  279. if ([self.hx_delegate respondsToSelector:@selector(photoNavigationViewControllerDidCancel:)]) {
  280. [self.hx_delegate photoNavigationViewControllerDidCancel:self];
  281. }
  282. }
  283. - (void)photoViewController:(HXPhotoViewController *)photoViewController didDoneAllList:(NSArray<HXPhotoModel *> *)allList photos:(NSArray<HXPhotoModel *> *)photoList videos:(NSArray<HXPhotoModel *> *)videoList original:(BOOL)original {
  284. if (!self.manager.configuration.requestImageAfterFinishingSelection) {
  285. [self clearAssetCacheWithAddOnWindow:!self.manager.selectPhotoFinishDismissAnimated];
  286. }
  287. if ([self.hx_delegate respondsToSelector:@selector(photoNavigationViewController:didDoneAllList:photos:videos:original:)]) {
  288. [self.hx_delegate photoNavigationViewController:self didDoneAllList:allList photos:photoList videos:videoList original:original];
  289. }
  290. }
  291. - (BOOL)shouldAutorotate{
  292. if (self.isCamera) {
  293. return NO;
  294. }
  295. if (self.manager.configuration.supportRotation) {
  296. return YES;
  297. }else {
  298. return NO;
  299. }
  300. }
  301. - (UIStatusBarStyle)preferredStatusBarStyle {
  302. return [self.topViewController preferredStatusBarStyle];
  303. }
  304. - (BOOL)prefersStatusBarHidden {
  305. return [self.topViewController prefersStatusBarHidden];
  306. }
  307. - (UIStatusBarAnimation)preferredStatusBarUpdateAnimation {
  308. return UIStatusBarAnimationFade;
  309. }
  310. //支持的方向
  311. - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
  312. if (self.isCamera) {
  313. return UIInterfaceOrientationMaskPortrait;
  314. }
  315. if (self.manager.configuration.supportRotation) {
  316. return UIInterfaceOrientationMaskAll;
  317. }else {
  318. return UIInterfaceOrientationMaskPortrait;
  319. }
  320. }
  321. - (void)clearAssetCache {
  322. [self clearAssetCacheWithAddOnWindow:NO];
  323. }
  324. - (void)clearAssetCacheWithAddOnWindow:(BOOL)addOnWindow {
  325. PHAsset *asset = self.cameraRollAlbumModel.assetResult.firstObject;
  326. if (asset) {
  327. [[PHImageManager defaultManager] cancelImageRequest:self.requestID];
  328. [HXPhotoCommon photoCommon].clearAssetRequestID = -1;
  329. PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
  330. options.deliveryMode = PHImageRequestOptionsDeliveryModeFastFormat;
  331. options.resizeMode = PHImageRequestOptionsResizeModeFast;
  332. options.synchronous = NO;
  333. options.networkAccessAllowed = NO;
  334. HXWeakSelf
  335. self.requestID = [HXAssetManager requestImageDataForAsset:asset options:options completion:^(NSData * _Nonnull imageData, UIImageOrientation orientation, NSDictionary<NSString *,id> * _Nonnull info) {
  336. [HXPhotoCommon photoCommon].clearAssetRequestID = -1;
  337. if (imageData) {
  338. if (addOnWindow || !weakSelf) {
  339. [HXCustomNavigationController addImageViewOnWindowWithImageData:imageData];
  340. }else {
  341. [weakSelf addImageViewWithImageData:imageData addOnWindow:addOnWindow];
  342. }
  343. }
  344. }];
  345. [HXPhotoCommon photoCommon].clearAssetRequestID = self.requestID;
  346. }
  347. }
  348. + (void)addImageViewOnWindowWithImageData:(NSData *)imageData {
  349. UIImage *image = [UIImage imageWithData:imageData];
  350. UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
  351. imageView.alpha = 0;
  352. imageView.userInteractionEnabled = NO;
  353. imageView.frame = [UIScreen mainScreen].bounds;
  354. [[UIApplication sharedApplication].keyWindow addSubview:imageView];
  355. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  356. [imageView removeFromSuperview];
  357. });
  358. }
  359. - (void)addImageViewWithImageData:(NSData *)imageData addOnWindow:(BOOL)addOnWindow {
  360. [self.imageView removeFromSuperview];
  361. UIImage *image = [UIImage imageWithData:imageData];
  362. UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
  363. imageView.alpha = 0;
  364. imageView.userInteractionEnabled = NO;
  365. imageView.frame = self.view.bounds;
  366. [self.view addSubview:imageView];
  367. self.imageView = imageView;
  368. }
  369. - (void)dealloc {
  370. if (_manager) {
  371. self.manager.selectPhotoing = NO;
  372. }
  373. if (_timer) {
  374. [_timer invalidate];
  375. _timer = nil;
  376. }
  377. if (HXShowLog) NSSLog(@"%@ dealloc", self);
  378. }
  379. @end