文档章节

iOS UIActivityViewController 分享视频,图片

n
 name扬
发布于 2015/02/05 16:08
字数 1331
阅读 257
收藏 1


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半年,写的不完全对,就当个参考吧(希望不要误人子弟),还有代码要亲自运行一下,才知道我说的对不对


© 著作权归作者所有

n
粉丝 0
博文 1
码字总数 1331
作品 0
郑州
私信 提问
iOS App之间传递数据的几种方式

UIDocumentInteractionController UIActivityViewController Shared Keychain Access Custom URL Scheme Web Service iCloud API UIPasteboard 参考 http://enharmonichq.com/sharing-data-l......

Redding
2014/12/05
2.2K
0
关于文件应用间共享的问题

在做一个文件管理的应用,其中一个功能是在系统已安装的其它App中打开某个文件 第一步需要在UIActivityViewController中列出所有支持改文件类型的已有App,如图: 但是用了UIActivityViewCon...

pixlee
2014/08/21
55
0
使用系统的UIActivityViewController实现分享功能遇到的问题

使用系统的UIActivityViewController实现分享功能,分享到QQ的链接,会自动加载成图片,能设置分享类型吗

YAYAYAYAJIE
2016/03/28
354
0
iOS 全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突

一、前期准备 有一个支持全屏侧滑返回的视图控制器ViewController,ViewController.view上有一个UIScrollView,UIScrollView上有UISlider。俺直接在之前的示例Demo上演示,简书地址:iOS 自定...

且行且珍惜_iOS
2018/08/17
0
0
iOS APP与APP之间的通信方式

1、URL Scheme 这个最常见了,基本接入分享、支付、地图的,都会用到 2、UIPasteboard 其实就是粘贴板,常见的就是淘口令啥的,也挺常见的 3、Keychain 这个就是一个安全的存储容器,本质其实...

RainOrz
02/26
57
0

没有更多内容

加载失败,请刷新页面

加载更多

关于AsyncTask的onPostExcute方法是否会在Activity重建过程中调用的问题

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/XG1057415595/article/details/86774575 假设下面一种情况...

shzwork
今天
6
0
object 类中有哪些方法?

getClass(): 获取运行时类的对象 equals():判断其他对象是否与此对象相等 hashcode():返回该对象的哈希码值 toString():返回该对象的字符串表示 clone(): 创建并返此对象的一个副本 wait...

happywe
今天
6
0
Docker容器实战(七) - 容器中进程视野下的文件系统

前两文中,讲了Linux容器最基础的两种技术 Namespace 作用是“隔离”,它让应用进程只能看到该Namespace内的“世界” Cgroups 作用是“限制”,它给这个“世界”围上了一圈看不见的墙 这么一...

JavaEdge
今天
8
0
文件访问和共享的方法介绍

在上一篇文章中,你了解到文件有三个不同的权限集。拥有该文件的用户有一个集合,拥有该文件的组的成员有一个集合,然后最终一个集合适用于其他所有人。在长列表(ls -l)中这些权限使用符号...

老孟的Linux私房菜
今天
7
0
面试套路题目

作者:抱紧超越小姐姐 链接:https://www.nowcoder.com/discuss/309292?type=3 来源:牛客网 面试时候的潜台词 抱紧超越小姐姐 编辑于 2019-10-15 16:14:56APP内打开赞 3 | 收藏 4 | 回复24 ...

MtrS
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部