LoginSignup
32
30

More than 5 years have passed since last update.

Photos.frameworkでカメラロールの画像を取得する

Last updated at Posted at 2016-11-20

環境

  • Xcode 8.1
  • Swift 3.0.1
  • えるたそ (OS X 10.11.6)
  • iOS10

準備

念のため Photos.framework を追加
Info.plistPrivacy - Photo Library Usage Description を追加しておきましょう!

画面設計

UICollectionView があって、 UICollectionViewCell のIdentifierがCellになっています。
また、セルのクラスは CameraRollCollectionViewCell としています。

ソースコード

ViewController.swift
import UIKit
import Photos

class ViewController: UIViewController {

    @IBOutlet weak var collectionView: UICollectionView!

    var photoAssets: Array! = [PHAsset]()

    override func viewDidLoad() {
        super.viewDidLoad()
        setup()
        libraryRequestAuthorization()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    fileprivate func setup() {
        collectionView.dataSource = self

        // UICollectionViewCellのマージン等の設定
        let flowLayout: UICollectionViewFlowLayout! = UICollectionViewFlowLayout()
        flowLayout.itemSize = CGSize(width: UIScreen.main.bounds.width / 3 - 4,
                                     height: UIScreen.main.bounds.width / 3 - 4)
        flowLayout.sectionInset = UIEdgeInsets(top: 8, left: 0, bottom: 0, right: 0)
        flowLayout.minimumInteritemSpacing = 0
        flowLayout.minimumLineSpacing = 6

        collectionView.collectionViewLayout = flowLayout
    }

    // カメラロールへのアクセス許可
    fileprivate func libraryRequestAuthorization() {
        PHPhotoLibrary.requestAuthorization({ [weak self] status in
            guard let wself = self else {
                return
            }
            switch status {
            case .authorized:
                wself.getAllPhotosInfo()
            case .denied:
                wself.showDeniedAlert()
            case .notDetermined:
                print("NotDetermined")
            case .restricted:
                print("Restricted")
            }
        })
    }

    // カメラロールから全て取得する
    fileprivate func getAllPhotosInfo() {
        let assets: PHFetchResult = PHAsset.fetchAssets(with: .image, options: nil)
        assets.enumerateObjects({ [weak self] (asset, index, stop) -> Void in
            guard let wself = self else {
                return
            }
            wself.photoAssets.append(asset as PHAsset)
        })
        collectionView.reloadData()
    }

    // カメラロールへのアクセスが拒否されている場合のアラート
    fileprivate func showDeniedAlert() {
        let alert: UIAlertController = UIAlertController(title: "エラー",
                                                         message: "「写真」へのアクセスが拒否されています。設定より変更してください。",
                                                         preferredStyle: .alert)
        let cancel: UIAlertAction = UIAlertAction(title: "キャンセル",
                                                  style: .cancel,
                                                  handler: nil)
        let ok: UIAlertAction = UIAlertAction(title: "設定画面へ",
                                              style: .default,
                                              handler: { [weak self] (action) -> Void in
                                                guard let wself = self else {
                                                    return
                                                }
                                                wself.transitionToSettingsApplition()
        })
        alert.addAction(cancel)
        alert.addAction(ok)
        present(alert, animated: true, completion: nil)
    }

    fileprivate func transitionToSettingsApplition() {
        let url = URL(string: UIApplicationOpenSettingsURLString)
        if let url = url {
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
        }
    }
}

extension ViewController : UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return photoAssets.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CameraRollCollectionViewCell
        cell.setConfigure(assets: photoAssets[indexPath.row])
        return cell
    }
}
CameraRollCollectionViewCell.swift
import UIKit
import Photos

class CameraRollCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var photoImageView: UIImageView!

    override func awakeFromNib() {
        super.awakeFromNib()
    }

    // 画像を表示する
    func setConfigure(assets: PHAsset) {
        let manager = PHImageManager()

        manager.requestImage(for: assets,
                             targetSize: frame.size,
                             contentMode: .aspectFill,
                             options: nil,
                             resultHandler: { [weak self] (image, info) in
                                guard let wself = self, let outImage = image else {
                                    return
                                }
                                wself.photoImageView.image = image
        })
    }
}

結果

スクリーンショット 2016-11-20 午後9.21.16.png

シミュレータのカメラロールには5つしか画像がないのですが、表示できました!

補足

上記リンクのコメントにあるようにカメラロールから画像を取得する時に時間がかかるのでそこは考慮しないといけません!コメントくださった @takabosoft さんありがとうございます:muscle:

最後に

削除とか検索条件を加えたりできるらしいのですが、いつか実装してみたいです。

参考

32
30
8

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
30