1.使用UIActivityViewController分享视频
代码如下:
NSMutableArray *itemsArray = [NSMutableArray array]; NSString *filePath = [[NSBundle mainBundle] pathForResource:@"temp" ofType:@"MP4"]; NSURL *url = [NSURL fileURLWithPath:filePath]; [itemsArray addObject:url]; UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:itemsArray applicationActivities:nil]; [self presentViewController:activityVC animated:YES completion:nil];
有点需要注意 url,在这里不是http连接,如果是http连接的话,在分享的界面不会有Save Video 的activity的
运行的效果:(在模拟器上跑的,可能和真机上有一定的差别,不过只要出现Save Video这个activity就说明可以成功分享Video了)
分享多个Video也很简单,itemsArray中多加几个url就行了(代码就不写了)。
2.使用UIActivityViewController分享5张以上的图片
在做项目的时候,有一个需求:用系统的UIActivityViewController 将多张图片保存到系统的相册,由上文看来貌似应该很简单(将filePath改成图片的文件路径就行了,如果5张以上就是一个NSArray包含多个url了),可是系统的保存有一些bug:也就是最多只能保存5张,而且iOS 系统会对高清的图片进行一定比例的压缩(会造成保存到手机的图片与保存之前的图片DPI不一样),在stack Overflow上有人提过这样问题,这是链接:http://stackoverflow.com/questions/18868547/iphone-multiple-image-sharing-using-uiactivityviewcontroller
相信很多人保存图片到系统相册用的都是
void UIImageWriteToSavedPhotosAlbum ( UIImage *image, id completionTarget, SEL completionSelector, void *contextInfo );
和这个callBack
- (void) image: (UIImage *) image didFinishSavingWithError: (NSError *) error contextInfo: (void *) contextInfo;
好了,如何解决呢?,系统的activity不支持5张以上,那么只能自定义一个activity了,先看下系统的SDK
typedef NS_ENUM(NSInteger, UIActivityCategory) { UIActivityCategoryAction, UIActivityCategoryShare, } // override methods //这个activity的类型:就是上面两种枚举类型,默认是UIActivityCategoryAction,具体有甚么区别,建议大家code试试 + (UIActivityCategory)activityCategory //下面3个函数,尽量都override吧,后两个理解起来不难,关键是activityType,SDK有说: //subclass may override to return custom activity type that is reported to completion handler,其实就是区分 activity,而且在completion handle可以获取到这个返回值。 - (NSString *)activityType; - (NSString *)activityTitle; - (UIImage *)activityImage; //这个函数我一般都是返回YES :如果你自定义一个activity,在分享图片的时候想让activity出现,而分享Video的时候,不想让这个activity出现,这返回值就可以控制是否显示 - (BOOL)canPerformWithActivityItems:(NSArray *)activityItems; //这个才是重点:在这个函数里面,解决只能保存5张图片的图片:顺便说一句activityItems,就是上面的【itemsArray】 - (void)prepareWithActivityItems:(NSArray *)activityItems; //下面这几个我也不是太了解。。。。。。 - (UIViewController *)activityViewController; - (void)performActivity; - (void)activityDidFinish:(BOOL)completed;
所以我们可以在- (void)prepareWithActivityItems:(NSArray *)activityItems 中遍历 activityItems 去保存图片,保存成功和失败不都是有一个回调么,如果失败了,那就重新保存一次(有点暴力)如果心情好的话,可以尝试一下信号量进行同步,不过目的一样,将所有的图片全部保存到系统相册中。
3.保存后图片的DPI不一致的问题(什么是DPI呢?姑且理解成像素吧)
也学你会遇见一很蛋疼的问题:如果你保存的图片像素非常的高,将图片保存到系统相册后前后的DPI会有一定的差别,像素越高差别越大
那么试试这个方法
//这里的data就是要保存的图片 - (void)saveImage:(NSData *)data { ALAssetsLibrary *assetLib = [[ALAssetsLibrary alloc] init]; [assetLib writeImageDataToSavedPhotosAlbum:data metadata:nil completionBlock:^(NSURL *assetURL, NSError *error) { if (error == nil) { }else{ //如果保存出错,就重复保存一下(暴力下无所谓) [self saveImage:data]; } }]; }
最后附上一个源码:
// // CustomActivity.h // GC // // Created by xuyang on 14-10-20. // #import <UIKit/UIKit.h> @interface CustomActivity : UIActivity{ dispatch_semaphore_t semphore; } + (UIActivityCategory)activityCategory; - (NSString *)activityType; // default returns nil. subclass may override to return custom activity type that is reported to completion handler - (NSString *)activityTitle; // default returns nil. subclass must override and must return non-nil value - (UIImage *)activityImage; // default returns nil. subclass must override and must return non-nil value @end ------------------------------ // // CustomActivity.m // GC // // Created by xuyang on 14-10-20. #import "CustomActivity.h" #import "AppDelegate.h" #import <AssetsLibrary/ALAssetsLibrary.h> static NSString * const HIPMustachifyActivityType = @"CoustomDelete"; @interface CustomActivity () { dispatch_queue_t queue; int itemsCount; int haveBeenSave; } @end @implementation CustomActivity + (UIActivityCategory)activityCategory { return UIActivityCategoryAction; } - (NSString *)activityType { return HIPMustachifyActivityType; } - (NSString *)activityTitle { return @"save to phone"; } - (UIImage *)activityImage { return [UIImage new]; } - (BOOL)canPerformWithActivityItems:(NSArray *)activityItems { return YES; } - (void)prepareWithActivityItems:(NSArray *)activityItems { semphore = dispatch_semaphore_create(0); // 创建信号量 queue = dispatch_queue_create("SaveImageOrVideo", NULL); itemsCount = [activityItems count]; dispatch_async(queue, ^(void) { for (id activityItem in activityItems) { NSData* data = [NSData dataWithContentsOfURL:activityItem]; UIImage* image = [UIImage imageWithData:data]; if (image) { //bug for image DIP [self saveImage:data AndPath:[(NSURL *)activityItem path]]; } else { [self saveVideoToPhotos:activityItem]; } dispatch_semaphore_wait(semphore, DISPATCH_TIME_FOREVER); // 等待信号. } }); } //bug for image DPI - (void)saveImage:(NSData *)data AndPath:(NSString *)filePath { ALAssetsLibrary *assetLib = [[ALAssetsLibrary alloc] init]; [assetLib writeImageDataToSavedPhotosAlbum:data metadata:nil completionBlock:^(NSURL *assetURL, NSError *error) { if (error == nil) { dispatch_semaphore_signal(semphore); }else{ [self saveImage:data AndPath:filePath]; } }]; } - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo { if (error != NULL){ NSLog(@"Error%@",error); dispatch_async(queue, ^(void) { // 图片保存失败,重新写入当前图片. UIImageWriteToSavedPhotosAlbum(image,self,@selector(image: didFinishSavingWithError:contextInfo:),contextInfo); }); }else{ dispatch_semaphore_signal(semphore); // 图片保存成功,发射信号量. } } #pragma mark 保存视频到手机相册中 -(void)saveVideoToPhotos:(id)activityItem{ ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; [library writeVideoAtPathToSavedPhotosAlbum:activityItem completionBlock:^(NSURL *assetURL, NSError *error) { if (error) { // 视频写入失败重新写入当前视频. [self saveVideoToPhotos:activityItem]; } else { dispatch_semaphore_signal(semphore); // 视频保存成功,发射信号量 } }]; } @end
刚做iOS半年,写的不完全对,就当个参考吧(希望不要误人子弟),还有代码要亲自运行一下,才知道我说的对不对