【Swift UIKit】画像をカメラロールに保存する方法!UIImageWriteToSavedPhotosAlbum

この記事からわかること
- SwiftのUIKitで画像をカメラロール(写真アプリのアルバム)に保存する方法
- NSCameraUsageDescriptionキーの指定
- UIImageWriteToSavedPhotosAlbumの使い方
index
[open]
\ アプリをリリースしました /
画像(UIImage)をカメラロール(写真アプリのアルバム)に保存する方法をまとめていきます。アプリ内からカメラを起動して写真を撮影する方法については以下の記事を参考にしてください。
おすすめ記事:【Swift UIKit】アプリ内からカメラで写真を撮影する方法!
UIImageWriteToSavedPhotosAlbumメソッド
参考文献:公式リファレンス:UIImageWriteToSavedPhotosAlbum
画像(UIImage)をカメラロールに保存するにはUIImageWriteToSavedPhotosAlbumメソッドを使用します。
func UIImageWriteToSavedPhotosAlbum(
_ image: UIImage,
_ completionTarget: Any?,
_ completionSelector: Selector?,
_ contextInfo: UnsafeMutableRawPointer?
)
- image:保存したい画像(UIImage)
- completionTarget:保存後にセレクターが呼び出されるオブジェクト
- completionSelector:保存後に呼び出すオブジェクトのメソッドセレクター
- contextInfo:セレクターに渡すコンテキスト固有のデータへのオプションのポインター
完了セレクターとして渡すメソッドは以下のシグネチャーに準拠する必要があります。
- (void)image:(UIImage *)image
didFinishSavingWithError:(NSError *)error
contextInfo:(void *)contextInfo;
おすすめ記事:【Swift UIKit】#selectorとは?使い方と@objcとsenderの意味まとめ
画像(UIImage)をカメラロールに保存する方法
では実際に画像(UIImage)をカメラロールに保存できるテストプログラムを作成していきたいと思います。
実装の流れ
- 「info.plist」にNSPhotoLibraryUsageDescriptionキーを追加
- アプリ内から写真を撮影する機能を実装
- 撮影した写真をUIImageViewに保存して表示
- UIImageViewに保存されている画像データをカメラロールに保存する
info.plistにNSPhotoLibraryUsageDescriptionキーを追加
アプリ内からデバイスのカメラロールにアクセスするためには「info.plist」にNSPhotoLibraryUsageDescriptionキーを追加する必要があります。

「info.plist」を開いたらKeyにNSPhotoLibraryUsageDescription
と入力し、Valueにはカメラロールを使用する旨を記載しておきます。自動でPrivacy - Photo Library Usage Description
に変換されます。
今回はカメラも使用するにでデバイスのカメラにアクセスできるようにNSCameraUsageDescriptionキーも追加しておきます。

アプリ内から写真を撮影する機能を実装
アプリ内から写真を撮影する機能の実装方法はコードのみ記述しておきます。こちらの記事を参考にしてください。
import UIKit
class ViewController: UIViewController {
// MARK: - ImageView
@IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: - 撮影ボタンアクション
@IBAction func takePictureTapped() {
if UIImagePickerController.isSourceTypeAvailable(.camera) {
let pickerView = UIImagePickerController()
pickerView.sourceType = .camera
pickerView.delegate = self
self.present(pickerView, animated: true)
}
}
}
extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let image = info[.originalImage] as! UIImage
imageView.image = image
self.dismiss(animated: true) // 選択画面を終了する
}
}
撮影した写真をUIImageViewに保存して表示
またViewController
を拡張してUIImagePickerControllerDelegate
に準拠させることでカメラで撮影した画像を取得し表示用のimageView
に格納しています。
UIImageViewに保存されている画像データをカメラロールに保存する
今回の本題であるカメラロールに保存する部分を実装していきます。Storyboardからボタンを追加し、紐付けるアクションを定義します。
まずは画像がちゃんと格納されているか(nilでないか)をguard〜else
構文で識別します。存在しない場合は処理を終了させます。問題なければ実際に画像を保存させるUIImageWriteToSavedPhotosAlbum
メソッドを呼び出して各引数に適切な値を渡していきます。
// MARK: - カメラロールに保存する
@IBAction func saveToPhotoLibraryTapped(_ sender: Any) {
guard let image = imageView.image else {
print("画像がないよ")
return
}
UIImageWriteToSavedPhotosAlbum(image, self, #selector(image(image:didFinishSavingWithError:contextInfo:)), nil)
}
image(image:didFinishSavingWithError:contextInfo:)メソッド
セレクターメソッドはシグネチャーに準じて定義していきます。error
がnil
かどうかで成功に可否を識別できます。
@objc func image(image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafeRawPointer) {
if let error = error {
print("失敗:\(error)")
} else {
print("写真の保存に成功したよ")
}
}
これで全ての実装が完了しました。正常に動作するか実機にビルドして確認してみてください。
全体のコード
import UIKit
class ViewController: UIViewController {
// MARK: - ImageView
@IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: -
@IBAction func taped(sender: UIButton) {
self.present(BarCodeReaderVC(), animated: true, completion: nil)
}
// MARK: - 撮影ボタンアクション
@IBAction func takePictureTapped() {
if UIImagePickerController.isSourceTypeAvailable(.camera) {
let pickerView = UIImagePickerController()
pickerView.sourceType = .camera
pickerView.delegate = self
self.present(pickerView, animated: true)
}
}
// MARK: - カメラロールに保存する
@IBAction func saveToPhotoLibraryTapped(_ sender: Any) {
guard let image = imageView.image else {
print("画像がないよ")
return
}
UIImageWriteToSavedPhotosAlbum(image, self, #selector(image(image:didFinishSavingWithError:contextInfo:)), nil)
}
@objc func image(image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafeRawPointer) {
if let error = error {
print("失敗:\(error)")
} else {
print("写真の保存に成功したよ")
}
}
}
extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let image = info[.originalImage] as! UIImage // カメラで撮影した画像を取得
imageView.image = image
self.dismiss(animated: true) // 選択画面を終了する
}
}
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。
個人開発に限界を感じたらiOSに特化したプログラミングスクール「iOSアカデミア」も検討してみてください!無料相談可能で「最短・最速」でiOSエンジニアになれるように手助けしてくれます。