距离上一个文章又是两个月...
起因
- 项目中的录屏视频是保存在用户相册的,如果用户打开同步到iCloud的操作,app内查看如果用户没用在相册中预先播放,是可能导致问题的.
- 公司不愿意放弃MWPhotoBrowser这个好几年没维护的老家伙,现在发现的一个坑可能只是其中之一
- 用cocoaPods 管理导入的MWPhotoBrowser,不想拉进项目修改源码.
翻车样子
ezgif.com-video-to-gif.gif
开始解决
从iCloud上同步
+ (void)getVideoWithAsset:(PHAsset *)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler success:(void (^)(NSURL *video, BOOL isInCloud))success failure:(void (^)(NSString *errorMessage))failure {
PHVideoRequestOptions* options = [[PHVideoRequestOptions alloc] init];
options.version = PHVideoRequestOptionsVersionOriginal;
options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
options.networkAccessAllowed = YES;
options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
WYDo_Block_Safe_Main4(progressHandler, progress, error, stop, info)
};
[[PHImageManager defaultManager] requestAVAssetForVideo:asset options:options resultHandler:^(AVAsset* avasset, AVAudioMix* audioMix, NSDictionary* info){
BOOL cloud = [[info objectForKey: PHImageResultIsInCloudKey] boolValue];
if (avasset) {
AVURLAsset *videoAsset = (AVURLAsset*)avasset;
WYDo_Block_Safe_Main2(success, videoAsset.URL, cloud);
} else {
WYDo_Block_Safe_Main1(failure, @"下载失败");
}
}];
}
这个代码很死板的,目的是拿到最终转化后的视频URL
.
可以看下获取前和获取后的URL.
- 获取前
file:///var/mobile/Media/PhotoData/Metadata/DCIM/102APPLE/IMG_2485.medium.MP4
- 获取后
file:///var/mobile/Media/DCIM/102APPLE/IMG_2485.MP4
开始处理
-
注意上诉方法的参数
PHAsset
,首先要先获取到点击播放的时候播放的PHAsset
.
1 新建MWPhotoBrowser的分类添加wy_asset属性
- (PHAsset *)wy_asset {
return objc_getAssociatedObject(self, @selector(wy_asset));
}
- (void)setWy_asset:(PHAsset *)wy_asset {
objc_setAssociatedObject(self, @selector(wy_asset), wy_asset, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
2 在MWPhotoBrowser
的代理中,获取asset并赋值
- (void)photoBrowser:(MWPhotoBrowser *)photoBrowser didDisplayPhotoAtIndex:(NSUInteger)index {
MWPhoto *photo = [_photos objectAtIndex:index];
PHAsset *asset = object_getIvar(photo, class_getInstanceVariable([MWPhoto class], "_asset"));
photoBrowser.wy_asset = asset;
}
因为在MWPhoto中asset是私有属性,这里用runtime获取了下
-
找到播放视频的方法,在播放之前改变视频URL
1 播放方法为_playVideo:atPhotoIndex:
,我们在类别中用方法交换加入我们自己的代码
+ (void)load {
WY_ExchangeInstanceImp(@selector(WY_playVideo:atPhotoIndex:), NSSelectorFromString(@"_playVideo:atPhotoIndex:"));
}
其中, WY_ExchangeInstanceImp
为
#define WY_ExchangeInstanceImp(sel1,sel2) \
method_exchangeImplementations(class_getInstanceMethod(self, sel1), class_getInstanceMethod(self, sel2));
2 在- (void)WY_playVideo:(NSURL *)videoURL atPhotoIndex:(NSUInteger)index
中获取iCloud视频地址
- (void)WY_playVideo:(NSURL *)videoURL atPhotoIndex:(NSUInteger)index {
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_queue_create("photo", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_enter(group);
__block NSURL *videoUrl = nil;
dispatch_async(queue, ^{
[MWPhotoBrowser getVideoWithAsset:self.wy_asset progressHandler:nil success:^(NSURL *video, BOOL isInCloud) {
videoUrl = video;
dispatch_group_leave(group);
} failure:^(NSString *errorMessage) {
dispatch_group_leave(group);
}];
});
dispatch_group_notify(group, queue, ^{
dispatch_async(dispatch_get_main_queue(), ^{
[self WY_playVideo:videoUrl atPhotoIndex:index];
});
});
}
这里是异步的获取URL,所以用了任务组dispatch_group_t
网友评论