Swift 自定义图片选择器(一) -- PhotosFramework介绍

先上最终效果图:


图片选择器效果图

使用前需要添加该框架,并且在文件头部 import photos

PhotosFramework

首先我们先了解一下PhotosFramework
Work with image and video assets managed by the Photos app, including those from iCloud Photo Library and Live Photos. Fetch and cache full-sized assets or thumbnails asynchronously, revise content, and sync revisions to multiple devices.

处理图像和视频资源,包括iCloud上的网络资源和本地资源。异步获取和缓存资源,保存资源修改,并且将修改同步到所有的设备中。
在这个项目中,我们只需要获取本地资源,并且展示出来。并没有涉及到iCloud和修改资源。

  • PHPhotoLibrary -- 管理照片库访问和更改的共享对象
  1. 用来获取相册的授权情况和请求授权

     let authorizationStatus = PHPhotoLibrary.authorizationStatus()
     switch authorizationStatus {
     case .authorized:
         print("已经授权")
         return true
     case .notDetermined:
         print("不确定是否授权")
         //一般是第一次打开app时的状态
         // 请求授权
         PHPhotoLibrary.requestAuthorization({ (status) in })
     case .denied:
         print("拒绝授权")
     case .restricted:
         print("限制授权")
         break
     }
    
    1. 对照片库进行更改或者是监听相册更改情况。前者应用一般是保存图片、视频等资源到系统相册中(这方面先不深入讨论)。
  • PHAsset 图片、视频等,我们在图片库中最终拿到的某一资源的对象,然后将该对象转换成UIImage,展示出来

    func getImageWithAsset(_ asset: PHAsset, size targetSize: CGSize, finishedCallack: @escaping (_ image: UIImage) -> ()) {
      let options = PHImageRequestOptions()
      options.resizeMode = .exact // 返回图像与目标size保持一致
      options.deliveryMode = .highQualityFormat   // 只返回高像素的图像
      var size = targetSize
      
      // 如果没有目标大小,则返回原图
      if targetSize == .zero {
          size = CGSize(width: asset.pixelWidth, height: asset.pixelHeight)
      }
      
      PHImageManager.default().requestImage(for: asset, targetSize: size, contentMode: .default, options: options) { (image, info) in
          // 如果是image是nil 则直接返回
          guard let image = image else {
              return
          }
          
          // 拿到图片,则返回
          finishedCallack(image)
      }
      }
    

上面的PHImageRequestOptions是用来设置请求图片的相关属性的。
options.resizeMode 表示:如果资源是压缩图片时,系统对图片解码时会参照targetSize的值。

  PHImageRequestOptions
  .fast 返回的图片可能会比targetSize大
  .exact 则与targetSize保持一致。

  options.deliveryMode 有以下取值:
  .opportunistic 会返回一张小图和大图
  .highQualityFormat 只返回大图
  .fastFormat 只返回小图
  • PHAssetCollection 表示PHAsset的集合,包括系统相册,用户创建的相册等。以下是获取智能相册的代码:

    func getSmartAlbums() -> [AlbumItem]? {
      //获取所有的智能相册
      let smartAlbums = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .albumRegular, options: nil)
      print("智能相册有\(smartAlbums.count)个")
      let options = PHFetchOptions()
      options.sortDescriptors = [NSSortDescriptor.init(key: "creationDate", ascending: true)]
      
      let albumsArray = getAssetResultInCollection(smartAlbums, fetchOptions: options)
      
      return albumsArray
     }
    
    func getAssetResultInCollection(_ collection: PHFetchResult<PHAssetCollection>, fetchOptions options: PHFetchOptions) ->[AlbumItem]? {
      var albumsArray = [AlbumItem]()
      
      for index in 0..<collection.count {
          //获取一个相册
          let assetCollection = collection[index];
          
          //然后从每一个智能相册中获取资源,获取到的是一个list
          let assetFecthResults = PHAsset.fetchAssets(in: assetCollection, options: nil);
          print("\(assetCollection.localizedTitle!)相册,共有照片数:\(assetFecthResults.count)")
          
          if assetFecthResults.count > 0 {
              //有照片的相册
              let album = AlbumItem.init(title: assetCollection.localizedTitle, fetchResult: assetFecthResults)
              
              albumsArray.append(album)
          }
      }
      
      return albumsArray
      }
    

结果如下:
智能相册打印结果

由此可见:smartAlbums是PHAssetCollection,是所有智能相册的集合,而该集合里面的元素assetCollection(表示的是某个智能相册)也是PHAssetCollection,包含的PHAsset就是一张照片。

  • PHCollection 抽象类,PHAssetCollection 和 PHCollectionList的父类,表示PHAsset的集合或者自身的集合。

  • PHCollectionList 表示照片库里面的文件夹,是PHAsset 和自身对象的集合。

  • PHFetchResult 表示有序的图片和图片集合的列表,smartAlbums 的具体类型应该是PHFetchResult<PHAssetCollection>, 意思是列表内的元素是PHAssetCollection,一般是用fetch method获取得到的结果。

    let smartAlbums = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .albumRegular, options: nil)
    
  • PHFetchOptions 使用fetch method时对结果进行管理的选项,譬如:排序条件,资源类型,是否收藏等。下面是以创建时间升序排序:

    let options = PHFetchOptions()
      options.sortDescriptors = [NSSortDescriptor.init(key: "creationDate", ascending: true)]
    
  • PHImageManager 提供获取图片UIImage对象、视频PlayerItem对象等方法。如果资源需要在界面上展示出来,需要使用该对象获取。
    例如从PHAsset中获取图片:

    PHImageManager.default().requestImage(for: asset, targetSize: size, contentMode: .default, options: options) { (image, info) in
          // 如果是image是nil 则直接返回
          guard let image = image else {
              return
          }
          
          // 拿到图片,则返回
          finishedCallack(image)
      }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,710评论 4 376
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,839评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,295评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,776评论 0 223
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,198评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,074评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,200评论 2 322
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,986评论 0 214
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,733评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,877评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,348评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,675评论 3 265
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,393评论 3 246
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,209评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,996评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,212评论 2 287
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 36,003评论 2 280