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

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

这次整理的是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];
    }
  });
}

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

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索ios
ios 获取系统相册、ios 获取系统相册图片、ios 获取系统相册路径、android 获取系统相册、安卓获取系统相册路径,以便于您获取更多的相关知识。

时间: 2024-09-27 13:37:59

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

iOS中获取系统相册中的图片实例_IOS

本文介绍了iOS中获取系统相册中的图片,在很多应用中都能用到,可以获取单张图片,也可以同时获取多张图片,废话不多说了,看下面吧. 一.获取单张图片 思路: 1.利用UIImagePickerController可以从系统自带的App(照片\相机)中获得图片 2.设置代理,遵守代理协议 注意这个UIImagePickerController类比较特殊,需要遵守两个代理协议 @interface ViewController () <UIImagePickerControllerDelegate,

使用wxPython获取系统剪贴板中的数据的教程

  这篇文章主要介绍了使用wxPython获取系统剪贴板中的数据的教程,wxPython是一个非常受欢迎的Python图形库,需要的朋友可以参考下 涉及到开发桌面程序,尤其是文本处理,剪贴板就很常用,不像 java 中那么烦锁,wxpython 中访问剪贴板非常简单,寥寥几句足以. ? 1 2 3 4 5 6 # 取得剪贴板并确保其为打开状态 text_obj = wx.TextDataObject() wx.TheClipboard.Open() if wx.TheClipboard.IsOp

ios-IOS获取系统相册图片名称在非ARC模式下报错

问题描述 IOS获取系统相册图片名称在非ARC模式下报错 dispatch_async(dispatch_get_main_queue(), ^{ ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset){ ALAssetRepresentation *representation = [myasset defaultRepresentation]; NSString *fileName = [represen

请问一下,为什么我把系统相册中的gif保存到沙盒之后就变成了静态图片?

问题描述 请问一下,为什么我把系统相册中的gif保存到沙盒之后就变成了静态图片? ALAssetRepresentation *representation = [asset defaultRepresentation]; NSString *document = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory NSUserDomainMask YES) lastObject]; NSString *filePath = [doc

android-Android中怎么通过从相册中选择图片来设置界面的背景图片

问题描述 Android中怎么通过从相册中选择图片来设置界面的背景图片 我想调用摄像头或者从相册中获取图片,把该图片设置为某个活动的背景图片,但不知道如何做,希望各位大神提供思路.就是想QQ聊天背景设置那样的.谢谢 解决方案 这个不难.分两步来,一步摄像头拍照存储/从相册读照片,这个csdn上很多例子demo,自己搜一下.第二步将图片读取到内存中,设置成背景就更不用说了. 解决方案二: 参考下:http://blog.csdn.net/jackyguo1992/article/details/2

excel图片-C# 获取Excel文件中的图片。是否需要第三方类库

问题描述 C# 获取Excel文件中的图片.是否需要第三方类库 要用C#程序做一个商品资料导入功能. Excel文件中有商品图片.商品图片所在的列是固定的,如何获取第一行的图片呢. 解决方案 微软的操作office的dll就行,或者NPIO 解决方案二: C#操作excel(读取excel里的图片并show在页面上) http://www.cnblogs.com/MR_ke/archive/2010/03/08/1680576.html

edittext插入图片-android Edittext中可以插入相册中的图片

问题描述 android Edittext中可以插入相册中的图片 最近在做一个发布的功能,是要在edittext中可以插入图片,然后形成图文混合,有哪位大神做过的可以指导一下吗? 解决方案 你组成html就行了,edittext可以解析html 解决方案二: 组成html也行,我记得好像有个开源的控件可以,你去搜搜 解决方案三: http://blog.csdn.net/cike110120/article/details/9106027这里讲的比较详细. 解决方案四: http://blog.

js获取文章内容中的图片

js获取文章内容中的图片 <Script language="VBScript"> <!-- msgbox getphoto("应明确写出问题所在或关键字<img src=""aaa.gif""/>霸王") Function getphoto(strHTML) Dim objRegExp, Match, Matches Set objRegExp = New Regexp objRegExp.Ig

Android获取SD卡中选中图片的路径(URL)示例

一个图片上传功能需要提供上传图片在SD卡中的路径,总结了网上的一些列子,修改了一下,代码很简单,感兴趣的朋友可以参考下哈,希望对大家有所帮助   最近在做一个图片上传的功能,需要提供上传图片在SD卡中的路径,在网上看了些例子,改改调试成功,代码很简单.其布局文件如下: 复制代码 代码如下: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://