当前位置: 移动技术网 > 移动技术>移动开发>IOS > iOS开发之获取系统相册中的图片与视频教程(内带url转换)

iOS开发之获取系统相册中的图片与视频教程(内带url转换)

2019年07月24日  | 移动技术网移动技术  | 我要评论

好些天没写点东西了,最近公司要做新项目,有点小忙。不想我的坚持就此中断,我把我前些天研究的东西拿出来给大家看看。

这次整理的是assetslibrary和photokit的使用。本人处女座,有点强迫症,之前写的项目里用的是assetslibrary写的调取相册内的媒体文件,但是xcode总是报警告错误,虽然能够编译并展示效果,但是十几个警告错误挂在那,心里总不是滋味,所以我就研究了一下assetlibrary和photokit。

在 ios 8 出现之前,开发者只能使用 assetslibrary 框架来访问设备的照片库,这是一个有点跟不上 ios 应用发展步伐以及代码设计原则但确实强大的框架,考虑到 ios7 仍占有不少的渗透率,因此 assetslibrary 也是本文重点介绍的部分。而在 ios8 出现之后,苹果提供了一个名为 photokit 的框架,一个可以让应用更好地与设备照片库对接的框架。

一、assetslibrary 组成

assetslibrary 的组成比较符合照片库本身的组成,照片库中的完整照片库对象、相册、相片都能在 assetslibrary 中找到一一对应的组成,这使到 assetslibrary 的使用变得直观而方便。想要了解assetslibrary得从它的类开始。

assetslibrary: 代表整个设备中的资源库(照片库),通过 assetslibrary 可以获取和包括设备中的照片和视频

  • alassetsgroup: 映射照片库中的一个相册,通过 alassetsgroup 可以获取某个相册的信息,相 册下的资源,同时也可以对某个相册添加资源。
  • alasset: 映射照片库中的一个照片或视频,通过 alasset 可以获取某个照片或视频的详细信息, 或者保存照片和视频。
  • alassetrepresentation: alassetrepresentation 是对 alasset 的封装(但不是其子类),可以更方便地获取 alasset 中的资源信息,每个 alasset 都有至少有一个 alassetrepresentation 对象,可以通过 defaultrepresentation 获取。而例如使用系统相机应用拍摄的 raw + jpeg 照片,则会有两个 alassetrepresentation,一个封装了照片的 raw 信息,另一个则封装了照片的 jpeg 信息。

@话不多说,直接上代码

#import <assetslibrary/assetslibrary.h> // 必须导入 
 
// 照片原图路径 
#define koriginalphotoimagepath  \ 
[[nssearchpathfordirectoriesindomains(nscachesdirectory, nsuserdomainmask, yes) objectatindex:0] stringbyappendingpathcomponent:@"originalphotoimages"] 
 
// 视频url路径 
#define kvideourlpath  \ 
[[nssearchpathfordirectoriesindomains(nscachesdirectory, nsuserdomainmask, yes) objectatindex:0] stringbyappendingpathcomponent:@"videourl"] 
 
// caches路径 
#define kcachespath  \ 
[nssearchpathfordirectoriesindomains(nscachesdirectory, nsuserdomainmask, yes) objectatindex:0] 
 
// mainviewcontroller 
@interface mthmainviewcontroller () 
 
@property (nonatomic,strong) mthnextviewcontroller *nextvc; 
@property (nonatomic,strong) nsmutablearray    *grouparrays; 
@property (nonatomic,strong) uiimageview      *litimgview; 
 
@end 
 
@implementation mthmainviewcontroller 
 
- (id)initwithnibname:(nsstring *)nibnameornil bundle:(nsbundle *)nibbundleornil 
{ 
  self = [super initwithnibname:nibnameornil bundle:nibbundleornil]; 
  if (self) { 
    // custom initialization 
  } 
  return self; 
} 
 
- (void)viewdidload 
{ 
  [super viewdidload]; 
  // do any additional setup after loading the view. 
  self.navigationitem.title = @"demo"; 
  self.view.backgroundcolor = [uicolor clearcolor]; 
   
  // 初始化 
  self.grouparrays = [nsmutablearray array]; 
   
  // 测试baritem 
  self.navigationitem.rightbarbuttonitem = [[uibarbuttonitem alloc] initwithtitle:@"测试" style:uibarbuttonitemstyleplain target:self action:@selector(testrun)]; 
   
  // 测试手势 
  uipangesturerecognizer *panrecognizer = [[uipangesturerecognizer alloc] initwithtarget:self action:@selector(didclickpangesturerecognizer:)]; 
  [self.navigationcontroller.view addgesturerecognizer:panrecognizer]; 
   
  // 图片或者视频的缩略图显示 
  self.litimgview = [[uiimageview alloc] initwithframe:cgrectmake(100, 200, 120, 120)]; 
  [self.view addsubview:_litimgview]; 
} 
 
 
- (void)testrun 
{ 
  __weak mthmainviewcontroller *weakself = self; 
  dispatch_async(dispatch_get_global_queue(dispatch_queue_priority_default, 0), ^{ 
    alassetslibrarygroupsenumerationresultsblock listgroupblock = ^(alassetsgroup *group, boolbool *stop) { 
      if (group != nil) { 
        [weakself.grouparrays addobject:group]; 
      } else { 
        [weakself.grouparrays enumerateobjectsusingblock:^(id obj, nsuinteger idx, boolbool *stop) { 
          [obj enumerateassetsusingblock:^(alasset *result, nsuinteger index, boolbool *stop) { 
            if ([result thumbnail] != nil) { 
              // 照片 
              if ([[result valueforproperty:alassetpropertytype] isequaltostring:alassettypephoto]){ 
                 
                nsdate *date= [result valueforproperty:alassetpropertydate]; 
                uiimage *image = [uiimage imagewithcgimage:[result thumbnail]]; 
                nsstring *filename = [[result defaultrepresentation] filename]; 
                nsurl *url = [[result defaultrepresentation] url]; 
                int64_t filesize = [[result defaultrepresentation] size]; 
                 
                nslog(@"date = %@",date); 
                nslog(@"filename = %@",filename); 
                nslog(@"url = %@",url); 
                nslog(@"filesize = %lld",filesize); 
                 
                // ui的更新记得放在主线程,要不然等子线程排队过来都不知道什么年代了,会很慢的 
                dispatch_async(dispatch_get_main_queue(), ^{ 
                  self.litimgview.image = image; 
                }); 
              } 
              // 视频 
              else if ([[result valueforproperty:alassetpropertytype] isequaltostring:alassettypevideo] ){ 
               
                // 和图片方法类似 
              } 
            } 
          }]; 
        }]; 
 
      } 
    }; 
     
    alassetslibraryaccessfailureblock failureblock = ^(nserror *error) 
    { 
       
      nsstring *errormessage = nil; 
       
      switch ([error code]) { 
        case alassetslibraryaccessuserdeniederror: 
        case alassetslibraryaccessgloballydeniederror: 
          errormessage = @"用户拒绝访问相册,请在<隐私>中开启"; 
          break; 
           
        default: 
          errormessage = @"reason unknown."; 
          break; 
      } 
       
      dispatch_async(dispatch_get_main_queue(), ^{ 
        uialertview *alertview = [[uialertview alloc]initwithtitle:@"错误,无法访问!" 
                                  message:errormessage 
                                 delegate:self 
                             cancelbuttontitle:@"确定" 
                             otherbuttontitles:nil, nil nil]; 
        [alertview show]; 
      }); 
    }; 
     
     
    alassetslibrary *assetslibrary = [[alassetslibrary alloc] init]; 
    [assetslibrary enumerategroupswithtypes:alassetsgroupall 
                   usingblock:listgroupblock failureblock:failureblock]; 
  }); 
} 


@但是:
按照上面方法直接取出来的路径是无法传输的,必须自己转化成nsdata对象重新写入沙盒路径

   // 将原始图片的url转化为nsdata数据,写入沙盒 
- (void)imagewithurl:(nsurl *)url withfilename:(nsstring *)filename 
{ 
  // 进这个方法的时候也应该加判断,如果已经转化了的就不要调用这个方法了 
  // 如何判断已经转化了,通过是否存在文件路径 
  alassetslibrary *assetlibrary = [[alassetslibrary alloc] init]; 
  // 创建存放原始图的文件夹--->originalphotoimages 
  nsfilemanager * filemanager = [nsfilemanager defaultmanager]; 
  if (![filemanager fileexistsatpath:koriginalphotoimagepath]) { 
    [filemanager createdirectoryatpath:koriginalphotoimagepath withintermediatedirectories:yes attributes:nil error:nil]; 
  } 
  dispatch_async(dispatch_get_global_queue(dispatch_queue_priority_default, 0), ^{ 
    if (url) { 
      // 主要方法 
      [assetlibrary assetforurl:url resultblock:^(alasset *asset) { 
        alassetrepresentation *rep = [asset defaultrepresentation]; 
        byte *buffer = (byte*)malloc((unsigned long)rep.size); 
        nsuinteger buffered = [rep getbytes:buffer fromoffset:0.0 length:((unsigned long)rep.size) error:nil]; 
        nsdata *data = [nsdata datawithbytesnocopy:buffer length:buffered freewhendone:yes]; 
        nsstring * imagepath = [koriginalphotoimagepath stringbyappendingpathcomponent:filename]; 
        [data writetofile:imagepath atomically:yes]; 
      } failureblock:nil]; 
    } 
  }); 
} 
 
// 将原始视频的url转化为nsdata数据,写入沙盒 
- (void)videowithurl:(nsurl *)url withfilename:(nsstring *)filename 
{ 
  // 解析一下,为什么视频不像图片一样一次性开辟本身大小的内存写入? 
  // 想想,如果1个视频有1g多,难道直接开辟1g多的空间大小来写? 
  alassetslibrary *assetlibrary = [[alassetslibrary alloc] init]; 
  dispatch_async(dispatch_get_global_queue(dispatch_queue_priority_default, 0), ^{ 
    if (url) { 
      [assetlibrary assetforurl:url resultblock:^(alasset *asset) { 
        alassetrepresentation *rep = [asset defaultrepresentation]; 
        nsstring * videopath = [kcachespath stringbyappendingpathcomponent:filename]; 
        char constconst *cvideopath = [videopath utf8string]; 
        filefile *file = fopen(cvideopath, "a+"); 
        if (file) { 
          const int buffersize = 11024 * 1024; 
          // 初始化一个1m的buffer 
          byte *buffer = (byte*)malloc(buffersize); 
          nsuinteger read = 0, offset = 0, written = 0; 
          nserror* err = nil; 
          if (rep.size != 0) 
          { 
            do { 
              read = [rep getbytes:buffer fromoffset:offset length:buffersize error:&err]; 
              written = fwrite(buffer, sizeof(char), read, file); 
              offset += read; 
            } while (read != 0 && !err);//没到结尾,没出错,ok继续 
          } 
          // 释放缓冲区,关闭文件 
          free(buffer); 
          buffer = null; 
          fclose(file); 
          file = null; 
        } 
      } failureblock:nil]; 
    } 
  }); 
} 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网