Skip to content

Commit 591c595

Browse files
authored
Merge pull request #1338 from shuLeesin/master
图片视频iCloud同步失败的UI提示和交互
2 parents 63a47e3 + 68f2dc4 commit 591c595

7 files changed

Lines changed: 134 additions & 34 deletions

File tree

TZImagePickerController/TZImagePickerController/TZAssetCell.m

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,13 @@ - (void)requestBigImage {
168168
}
169169

170170
_bigImageRequestID = [[TZImageManager manager] requestImageDataForAsset:_model.asset completion:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
171+
if (!imageData && [info[PHImageResultIsInCloudKey] boolValue]) {
172+
self.model.iCloudFailed = YES;
173+
if (self.didSelectPhotoBlock) {
174+
self.didSelectPhotoBlock(YES);
175+
self.selectImageView.image = self.photoDefImage;
176+
}
177+
}
171178
[self hideProgressView];
172179
} progressHandler:^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
173180
if (self.model.isSelected) {
@@ -185,6 +192,19 @@ - (void)requestBigImage {
185192
[self cancelBigImageRequest];
186193
}
187194
}];
195+
if (_model.type == TZAssetCellTypeVideo) {
196+
[[TZImageManager manager] getVideoWithAsset:_model.asset completion:^(AVPlayerItem *playerItem, NSDictionary *info) {
197+
if (!playerItem && [info[PHImageResultIsInCloudKey] boolValue]) {
198+
dispatch_async(dispatch_get_main_queue(), ^{
199+
self->_model.iCloudFailed = YES;
200+
if (self->_didSelectPhotoBlock) {
201+
self->_didSelectPhotoBlock(YES);
202+
self->_selectImageView.image = self.photoDefImage;
203+
}
204+
});
205+
}
206+
}];
207+
}
188208
}
189209

190210
- (void)cancelBigImageRequest {

TZImagePickerController/TZImagePickerController/TZAssetModel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ typedef enum : NSUInteger {
2424
@property (nonatomic, assign) BOOL isSelected; ///< The select status of a photo, default is No
2525
@property (nonatomic, assign) TZAssetModelMediaType type;
2626
@property (nonatomic, copy) NSString *timeLength;
27+
@property (nonatomic, assign) BOOL iCloudFailed;
2728

2829
/// Init a photo dataModel With a PHAsset
2930
/// 用一个PHAsset实例,初始化一个照片模型

TZImagePickerController/TZImagePickerController/TZPhotoPickerController.m

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,11 @@ - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cell
566566
[[NSNotificationCenter defaultCenter] postNotificationName:@"TZ_PHOTO_PICKER_RELOAD_NOTIFICATION" object:strongSelf.navigationController];
567567
}
568568
[UIView showOscillatoryAnimationWithLayer:strongLayer type:TZOscillatoryAnimationToSmaller];
569+
if (strongCell.model.iCloudFailed) {
570+
[strongSelf->_models replaceObjectAtIndex:indexPath.item withObject:strongCell.model];
571+
NSString *title = [NSBundle tz_localizedStringForKey:@"iCloud sync failed"];
572+
[tzImagePickerVc showAlertWithTitle:title];
573+
}
569574
} else {
570575
// 2. select:check if over the maxImagesCount / 选择照片,检查是否超过了最大个数的限制
571576
if (tzImagePickerVc.selectedModels.count < tzImagePickerVc.maxImagesCount) {

TZImagePickerController/TZImagePickerController/TZPhotoPreviewCell.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@
3838
@property (nonatomic, strong) UIScrollView *scrollView;
3939
@property (nonatomic, strong) UIView *imageContainerView;
4040
@property (nonatomic, strong) TZProgressView *progressView;
41-
@property (nonatomic, strong) UIView *iCloudErrorView; // iCloud加载失败提示View
41+
@property (nonatomic, strong) UIImageView *iCloudErrorIcon;
42+
@property (nonatomic, strong) UILabel *iCloudErrorLabel;
43+
@property (nonatomic, copy) void (^iCloudSyncFailedHandle)(id asset, BOOL isSyncFailed);
44+
4245

4346
@property (nonatomic, assign) BOOL allowCrop;
4447
@property (nonatomic, assign) CGRect cropRect;
@@ -61,6 +64,9 @@
6164
@property (strong, nonatomic) UIButton *playButton;
6265
@property (strong, nonatomic) UIImage *cover;
6366
@property (nonatomic, strong) NSURL *videoURL;
67+
@property (nonatomic, strong) UIImageView *iCloudErrorIcon;
68+
@property (nonatomic, strong) UILabel *iCloudErrorLabel;
69+
@property (nonatomic, copy) void (^iCloudSyncFailedHandle)(id asset, BOOL isSyncFailed);
6470
- (void)pausePlayerAndShowNaviBar;
6571
@end
6672

TZImagePickerController/TZImagePickerController/TZPhotoPreviewCell.m

Lines changed: 58 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ - (void)configSubviews {
6666

6767
- (void)setModel:(TZAssetModel *)model {
6868
[super setModel:model];
69-
_previewView.asset = model.asset;
69+
_previewView.model = model;
7070
}
7171

7272
- (void)recoverSubviews {
@@ -133,20 +133,17 @@ - (instancetype)initWithFrame:(CGRect)frame {
133133
_imageView.contentMode = UIViewContentModeScaleAspectFill;
134134
_imageView.clipsToBounds = YES;
135135
[_imageContainerView addSubview:_imageView];
136-
137-
_iCloudErrorView = [[UIView alloc] initWithFrame:CGRectMake(0, [TZCommonTools tz_isIPhoneX] ? 88 : 64, self.tz_width, 28)];
138-
UIImageView *icloud = [[UIImageView alloc] init];
139-
icloud.image = [UIImage tz_imageNamedFromMyBundle:@"iCloudError"];
140-
icloud.frame = CGRectMake(10, 0, 28, 28);
141-
[_iCloudErrorView addSubview:icloud];
142-
UILabel *label = [[UILabel alloc] init];
143-
label.frame = CGRectMake(40, 0, self.tz_width - 50, 28);
144-
label.font = [UIFont systemFontOfSize:10];
145-
label.textColor = [UIColor whiteColor];
146-
label.text = [NSBundle tz_localizedStringForKey:@"iCloud sync failed"];
147-
[_iCloudErrorView addSubview:label];
148-
[self addSubview:_iCloudErrorView];
149-
_iCloudErrorView.hidden = YES;
136+
137+
_iCloudErrorIcon = [[UIImageView alloc] init];
138+
_iCloudErrorIcon.image = [UIImage tz_imageNamedFromMyBundle:@"iCloudError"];
139+
_iCloudErrorIcon.hidden = YES;
140+
[self addSubview:_iCloudErrorIcon];
141+
_iCloudErrorLabel = [[UILabel alloc] init];
142+
_iCloudErrorLabel.font = [UIFont systemFontOfSize:10];
143+
_iCloudErrorLabel.textColor = [UIColor whiteColor];
144+
_iCloudErrorLabel.text = [NSBundle tz_localizedStringForKey:@"iCloud sync failed"];
145+
_iCloudErrorLabel.hidden = YES;
146+
[self addSubview:_iCloudErrorLabel];
150147

151148
UITapGestureRecognizer *tap1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTap:)];
152149
[self addGestureRecognizer:tap1];
@@ -173,12 +170,15 @@ - (void)setModel:(TZAssetModel *)model {
173170
if (model.type == TZAssetModelMediaTypePhotoGif) {
174171
// 先显示缩略图
175172
[[TZImageManager manager] getPhotoWithAsset:model.asset completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) {
176-
if (!photo && [info[PHImageResultIsInCloudKey] boolValue]) {
177-
self.iCloudErrorView.hidden = NO;
178-
} else {
179-
self.iCloudErrorView.hidden = YES;
173+
BOOL iCloudSyncFailed = !photo && [info[PHImageResultIsInCloudKey] boolValue];
174+
self.iCloudErrorLabel.hidden = !iCloudSyncFailed;
175+
self.iCloudErrorIcon.hidden = !iCloudSyncFailed;
176+
if (self.iCloudSyncFailedHandle) {
177+
self.iCloudSyncFailedHandle(model.asset, iCloudSyncFailed);
178+
}
179+
if (photo) {
180+
self.imageView.image = photo;
180181
}
181-
self.imageView.image = photo;
182182
[self resizeSubviews];
183183
if (self.isRequestingGIF) {
184184
return;
@@ -223,13 +223,16 @@ - (void)setAsset:(PHAsset *)asset {
223223

224224
_asset = asset;
225225
self.imageRequestID = [[TZImageManager manager] getPhotoWithAsset:asset completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) {
226+
BOOL iCloudSyncFailed = !photo && [info[PHImageResultIsInCloudKey] boolValue];
227+
self.iCloudErrorLabel.hidden = !iCloudSyncFailed;
228+
self.iCloudErrorIcon.hidden = !iCloudSyncFailed;
229+
if (self.iCloudSyncFailedHandle) {
230+
self.iCloudSyncFailedHandle(asset, iCloudSyncFailed);
231+
}
226232
if (![asset isEqual:self->_asset]) return;
227-
if (!photo && [info[PHImageResultIsInCloudKey] boolValue]) {
228-
self.iCloudErrorView.hidden = NO;
229-
} else {
230-
self.iCloudErrorView.hidden = YES;
233+
if (photo) {
234+
self.imageView.image = photo;
231235
}
232-
self.imageView.image = photo;
233236
[self resizeSubviews];
234237
if (self.imageView.tz_height && self.allowCrop) {
235238
CGFloat scale = MAX(self.cropRect.size.width / self.imageView.tz_width, self.cropRect.size.height / self.imageView.tz_height);
@@ -240,7 +243,7 @@ - (void)setAsset:(PHAsset *)asset {
240243
[self.scrollView setZoomScale:scale animated:YES];
241244
}
242245
}
243-
246+
244247
self->_progressView.hidden = YES;
245248
if (self.imageProgressUpdateBlock) {
246249
self.imageProgressUpdateBlock(1);
@@ -337,8 +340,9 @@ - (void)layoutSubviews {
337340
CGFloat progressX = (self.tz_width - progressWH) / 2;
338341
CGFloat progressY = (self.tz_height - progressWH) / 2;
339342
_progressView.frame = CGRectMake(progressX, progressY, progressWH, progressWH);
340-
341343
[self recoverSubviews];
344+
_iCloudErrorIcon.frame = CGRectMake(20, [TZCommonTools tz_isIPhoneX] ? 88 + 10 : 64 + 10, 28, 28);
345+
_iCloudErrorLabel.frame = CGRectMake(53, [TZCommonTools tz_isIPhoneX] ? 88 + 10 : 64 + 10, self.tz_width - 63, 28);
342346
}
343347

344348
#pragma mark - UITapGestureRecognizer Event
@@ -395,6 +399,14 @@ @implementation TZVideoPreviewCell
395399

396400
- (void)configSubviews {
397401
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillResignActiveNotification) name:UIApplicationWillResignActiveNotification object:nil];
402+
_iCloudErrorIcon = [[UIImageView alloc] init];
403+
_iCloudErrorIcon.image = [UIImage tz_imageNamedFromMyBundle:@"iCloudError"];
404+
_iCloudErrorIcon.hidden = YES;
405+
_iCloudErrorLabel = [[UILabel alloc] init];
406+
_iCloudErrorLabel.font = [UIFont systemFontOfSize:10];
407+
_iCloudErrorLabel.textColor = [UIColor whiteColor];
408+
_iCloudErrorLabel.text = [NSBundle tz_localizedStringForKey:@"iCloud sync failed"];
409+
_iCloudErrorLabel.hidden = YES;
398410
}
399411

400412
- (void)configPlayButton {
@@ -406,6 +418,8 @@ - (void)configPlayButton {
406418
[_playButton setImage:[UIImage tz_imageNamedFromMyBundle:@"MMVideoPreviewPlayHL"] forState:UIControlStateHighlighted];
407419
[_playButton addTarget:self action:@selector(playButtonClick) forControlEvents:UIControlEventTouchUpInside];
408420
[self addSubview:_playButton];
421+
[self addSubview:_iCloudErrorIcon];
422+
[self addSubview:_iCloudErrorLabel];
409423
}
410424

411425
- (void)setModel:(TZAssetModel *)model {
@@ -428,10 +442,24 @@ - (void)configMoviePlayer {
428442

429443
if (self.model && self.model.asset) {
430444
[[TZImageManager manager] getPhotoWithAsset:self.model.asset completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) {
431-
self.cover = photo;
445+
BOOL iCloudSyncFailed = !photo && [info[PHImageResultIsInCloudKey] boolValue];
446+
self.iCloudErrorLabel.hidden = !iCloudSyncFailed;
447+
self.iCloudErrorIcon.hidden = !iCloudSyncFailed;
448+
if (self.iCloudSyncFailedHandle) {
449+
self.iCloudSyncFailedHandle(self.model.asset, iCloudSyncFailed);
450+
}
451+
if (photo) {
452+
self.cover = photo;
453+
}
432454
}];
433455
[[TZImageManager manager] getVideoWithAsset:self.model.asset completion:^(AVPlayerItem *playerItem, NSDictionary *info) {
434456
dispatch_async(dispatch_get_main_queue(), ^{
457+
BOOL iCloudSyncFailed = !playerItem && [info[PHImageResultIsInCloudKey] boolValue];
458+
self.iCloudErrorLabel.hidden = !iCloudSyncFailed;
459+
self.iCloudErrorIcon.hidden = !iCloudSyncFailed;
460+
if (self.iCloudSyncFailedHandle) {
461+
self.iCloudSyncFailedHandle(self.model.asset, iCloudSyncFailed);
462+
}
435463
[self configPlayerWithItem:playerItem];
436464
});
437465
}];
@@ -455,6 +483,8 @@ - (void)layoutSubviews {
455483
[super layoutSubviews];
456484
_playerLayer.frame = self.bounds;
457485
_playButton.frame = CGRectMake(0, 64, self.tz_width, self.tz_height - 64 - 44);
486+
_iCloudErrorIcon.frame = CGRectMake(20, [TZCommonTools tz_isIPhoneX] ? 88 + 10 : 64 + 10, 28, 28);
487+
_iCloudErrorLabel.frame = CGRectMake(53, [TZCommonTools tz_isIPhoneX] ? 88 + 10 : 64 + 10, self.tz_width - 63, 28);
458488
}
459489

460490
- (void)photoPreviewCollectionViewDidScroll {

TZImagePickerController/TZImagePickerController/TZPhotoPreviewController.m

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ @interface TZPhotoPreviewController ()<UICollectionViewDataSource,UICollectionVi
4242

4343
@property (nonatomic, assign) double progress;
4444
@property (strong, nonatomic) UIAlertController *alertView;
45+
@property (nonatomic, strong) UIView *iCloudErrorView;
4546
@end
4647

4748
@implementation TZPhotoPreviewController
@@ -441,7 +442,6 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
441442
_currentIndex = currentIndex;
442443
[self refreshNaviBarAndBottomBarState];
443444
}
444-
445445
[[NSNotificationCenter defaultCenter] postNotificationName:@"photoPreviewCollectionViewDidScroll" object:nil];
446446
}
447447

@@ -459,8 +459,20 @@ - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cell
459459
__weak typeof(self) weakSelf = self;
460460
if (_tzImagePickerVc.allowPickingMultipleVideo && model.type == TZAssetModelMediaTypeVideo) {
461461
cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"TZVideoPreviewCell" forIndexPath:indexPath];
462+
TZVideoPreviewCell *currentCell = (TZVideoPreviewCell *)cell;
463+
currentCell.iCloudSyncFailedHandle = ^(id asset, BOOL isSyncFailed) {
464+
model.iCloudFailed = isSyncFailed;
465+
[weakSelf didICloudSyncStatusChanged:model];
466+
[weakSelf.models replaceObjectAtIndex:indexPath.item withObject:model];
467+
};
462468
} else if (_tzImagePickerVc.allowPickingMultipleVideo && model.type == TZAssetModelMediaTypePhotoGif && _tzImagePickerVc.allowPickingGif) {
463469
cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"TZGifPreviewCell" forIndexPath:indexPath];
470+
TZGifPreviewCell *currentCell = (TZGifPreviewCell *)cell;
471+
currentCell.previewView.iCloudSyncFailedHandle = ^(id asset, BOOL isSyncFailed) {
472+
model.iCloudFailed = isSyncFailed;
473+
[weakSelf didICloudSyncStatusChanged:model];
474+
[weakSelf.models replaceObjectAtIndex:indexPath.item withObject:model];
475+
};
464476
} else {
465477
cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"TZPhotoPreviewCell" forIndexPath:indexPath];
466478
TZPhotoPreviewCell *photoPreviewCell = (TZPhotoPreviewCell *)cell;
@@ -485,13 +497,19 @@ - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cell
485497
}
486498
}
487499
}];
500+
photoPreviewCell.previewView.iCloudSyncFailedHandle = ^(id asset, BOOL isSyncFailed) {
501+
model.iCloudFailed = isSyncFailed;
502+
[weakSelf didICloudSyncStatusChanged:model];
503+
[weakSelf.models replaceObjectAtIndex:indexPath.item withObject:model];
504+
};
488505
}
489506

490507
cell.model = model;
491508
[cell setSingleTapGestureBlock:^{
492509
__strong typeof(weakSelf) strongSelf = weakSelf;
493510
[strongSelf didTapPreviewCell];
494511
}];
512+
495513
return cell;
496514
}
497515

@@ -562,7 +580,8 @@ - (void)refreshNaviBarAndBottomBarState {
562580
_originalPhotoLabel.hidden = YES;
563581
_doneButton.hidden = YES;
564582
}
565-
583+
// iCloud同步失败的UI刷新
584+
[self didICloudSyncStatusChanged:model];
566585
if (_tzImagePickerVc.photoPreviewPageDidRefreshStateBlock) {
567586
_tzImagePickerVc.photoPreviewPageDidRefreshStateBlock(_collectionView, _naviBar, _backButton, _selectButton, _indexLabel, _toolBar, _originalPhotoButton, _originalPhotoLabel, _doneButton, _numberImageView, _numberLabel);
568587
}
@@ -578,6 +597,25 @@ - (void)refreshSelectButtonImageViewContentMode {
578597
});
579598
}
580599

600+
- (void)didICloudSyncStatusChanged:(TZAssetModel *)model{
601+
dispatch_async(dispatch_get_main_queue(), ^{
602+
TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
603+
// onlyReturnAsset为NO时,依赖TZ返回大图,所以需要有iCloud同步失败的提示,并且不能选择,
604+
if (_tzImagePickerVc.onlyReturnAsset) {
605+
return;
606+
}
607+
TZAssetModel *currentModel = self.models[self.currentIndex];
608+
if (_tzImagePickerVc.selectedModels.count <= 0) {
609+
self->_doneButton.enabled = !currentModel.iCloudFailed;
610+
} else {
611+
self->_doneButton.enabled = YES;
612+
}
613+
self->_selectButton.hidden = currentModel.iCloudFailed;
614+
self->_originalPhotoButton.hidden = currentModel.iCloudFailed;
615+
self->_originalPhotoLabel.hidden = currentModel.iCloudFailed;
616+
});
617+
}
618+
581619
- (void)showPhotoBytes {
582620
[[TZImageManager manager] getPhotosBytesWithArray:@[_models[self.currentIndex]] completion:^(NSString *totalBytes) {
583621
self->_originalPhotoLabel.text = [NSString stringWithFormat:@"(%@)",totalBytes];

TZImagePickerController/TZImagePickerController/TZVideoPlayerController.m

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,13 +224,13 @@ - (void)pausePlayerAndShowNaviBar {
224224
#pragma mark - lazy
225225
- (UIView *)iCloudErrorView{
226226
if (!_iCloudErrorView) {
227-
_iCloudErrorView = [[UIView alloc] initWithFrame:CGRectMake(0, [TZCommonTools tz_isIPhoneX] ? 88 : 64, self.view.tz_width, 28)];
227+
_iCloudErrorView = [[UIView alloc] initWithFrame:CGRectMake(0, [TZCommonTools tz_isIPhoneX] ? 88 + 10 : 64 + 10, self.view.tz_width, 28)];
228228
UIImageView *icloud = [[UIImageView alloc] init];
229229
icloud.image = [UIImage tz_imageNamedFromMyBundle:@"iCloudError"];
230-
icloud.frame = CGRectMake(10, 0, 28, 28);
230+
icloud.frame = CGRectMake(20, 0, 28, 28);
231231
[_iCloudErrorView addSubview:icloud];
232232
UILabel *label = [[UILabel alloc] init];
233-
label.frame = CGRectMake(40, 0, self.view.tz_width - 50, 28);
233+
label.frame = CGRectMake(53, 0, self.view.tz_width - 63, 28);
234234
label.font = [UIFont systemFontOfSize:10];
235235
label.textColor = [UIColor whiteColor];
236236
label.text = [NSBundle tz_localizedStringForKey:@"iCloud sync failed"];

0 commit comments

Comments
 (0)