Swift - 画像ファイルを Photo Library に保存・取得する方法

ここでは、Swift で画像ファイルを写真ライブラリ (Photo Library) に保存・取得する方法をご説明します。

前回 「カメラで写真を撮る方法」で、Take Photo というボタンをタップした時に、カメラが起動して写真を撮り、元の画面に撮った写真が表示されるアプリを作りました。

今回はそのアプリに Save to Photo Library、Clear Photo、Select from Photo Library の三つのボタンを追加して、画像ファイルを Photo Library に保存・取得する機能を追加します。

写真を撮る iOS アプリにボタンとアクションを追加する

まずは、カメラで写真を撮る iOS アプリに、今回テストに使う三つのボタンを追加して、アクションを作っておきます。

カメラで写真を撮る iOS アプリをまだ作っていない方は「カメラで写真を撮る方法」を参考に作っておいてください。

プロジェクトを開き、Main ストーリーボードの View Controller の Take Photo ボタンの下に、Save to Photo Library、Clear Photo、Select from Photo Library の三つのボタンを追加します。

ここでは Stack View に入れていますが、配置や色など、適当で大丈夫です。

Swift - 画像ファイルを写真ライブラリに保存・取得する方法 1


Save to Photo Library、Clear Photo、Select from Photo Library ボタンから、それぞれ、saveToPhotoLibraryTapped、clearPhotoTapped、selectFromPhotoLibraryTapped という名前で TouchUpInside のアクションを作っておきます。

Swift - 画像ファイルを写真ライブラリに保存・取得する方法 2

@IBAction func saveToPhotoLibraryTapped(_ sender: Any) {
}

@IBAction func clearPhotoTapped(_ sender: Any) {
}

@IBAction func selectFromPhotoLibraryTapped(_ sender: Any) {
}

Clear Photo ボタンをタップした時には、UIImageView の画像を削除したいので、次の一行のコードを追加しておきます。

imageView は UIImageView のアウトレットです。

@IBAction func clearPhotoTapped(_ sender: Any) {
    imageView.image = nil
}

Swift で画像ファイルを Photo Library に保存する方法

Swift で Photo Library に UIImageView に表示されている写真を保存します。

まず、iOS アプリ内で Photo Library に画像を保存・取得するのに、info.plist に Privacy - Photo Library Usage Description (NSPhotoLibraryUsageDescription) と Privacy - Photo Library Additions Usage Description (NSPhotoLibraryAddUsageDescription) を追加しておきます。

Swift - 画像ファイルを写真ライブラリに保存・取得する方法 3

Privacy - Photo Library Usage Description (NSPhotoLibraryUsageDescription) だけでも、Photo Library に写真を保存できることはできるのですが、エラーが出ることがあるので、Photo Library への書き込み専用の Privacy - Photo Library Additions Usage Description (NSPhotoLibraryAddUsageDescription) も追加しています。


続いて、Save to Photo Library ボタンをタップした時に、UIImageView の image を Photo Library に保存するコードを書きます。

ViewController.swift に先ほど作った saveToPhotoLibraryTapped() を以下のように変更し、image() も追加します。

@IBAction func saveToPhotoLibraryTapped(_ sender: Any) {
    guard let image = imageView.image else { 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("Failed to save photo: \(error)")
    } else {
        print("Photo saved successfully.")
    }
}

2 行目では、guard let で imageView(UIImageView のアウトレット)から image データを取得し、もし取得できなかったら return しています。

3 行目で UIImageWriteToSavedPhotosAlbum() メソッドを使って、画像データを Photo Library のカメラロールのアルバムに保存しています。

UIImageWriteToSavedPhotosAlbum の構文は以下の通りで、第二引数と第三引数で、保存処理後にこの View Controller の image() が呼ばれるように指定しています。

@func UIImageWriteToSavedPhotosAlbum(_ image: UIImage, 
                                     _ completionTarget: Any?, 
                                     _ completionSelector: Selector?, 
                                     _ contextInfo: UnsafeMutableRawPointer?)}

6 行目から 11 行目の image() 内では、error が入っている時は、エラーメッセージを、成功した時は "Photo saved successfully." をプリントするようにしています。


画像ファイルを Photo Library に保存するコードは以上です。

Swift で画像を Photo Library から選択して表示する方法

次は、Swift で写真ライブラリ (Photo Library) に保存されている画像を取得します。


Select from Photo Library ボタンをタップした時に、Photo Library から写真を選択する Image Picker 画面をたちあげ、選択された 画像を UIImageView に表示するコードを書きます。

UIImagePickerController はカメラで写真を撮る時にも使いましたが、それとほぼ同じ方法で sourceType を .camera から .photoLibrary に変更するだけで、Photo Library から写真を選択することができます。


カメラとフォトライブラリで同じ UIImagePickerController を使うようにコードを変更します。

こちらが変更後の ViewController.swift で、ハイライトされている箇所が変更した箇所です。

import UIKit

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    @IBOutlet weak var imageView: UIImageView!
    var imagePicker: UIImagePickerController!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        imagePicker = UIImagePickerController()
        imagePicker.delegate = self
    }
    
    @IBAction func takePhotoTapped(_ sender: Any) {
        if UIImagePickerController.isSourceTypeAvailable(.camera) {
            imagePicker.sourceType = .camera
            self.present(imagePicker, animated: true, completion: nil)
        }
        else {
            print("Camera not available.")
        }
    }
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        picker.dismiss(animated: true)

        guard let image = info[.originalImage] as? UIImage else {
            print("Image not found.")
            return
        }

        imageView.image = image
    }
    
    @IBAction func saveToPhotoLibraryTapped(_ sender: Any) {
        guard let image = imageView.image else { 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("Failed to save photo: \(error)")
        } else {
            print("Photo saved successfully.")
        }
    }
    
    @IBAction func clearPhotoTapped(_ sender: Any) {
        imageView.image = nil
    }
    
    @IBAction func selectFromPhotoLibraryTapped(_ sender: Any) {
        if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
            imagePicker.sourceType = .photoLibrary
            self.present(imagePicker, animated: true, completion: nil)
        }
        else {
            print("Photo Library not available.")
        }
    }
}

54 ~ 60 行目が、Select from Photo Library ボタンがタップされた時に実行されるコードです。

54 行目で Photo Library が利用可能かチェックしています。

55 行目で UIImagePickerController の sourceType を .photoLibrary に設定しています。

56 行目の self.present() メソッドで、UIImagePickerController を表示し、Photo Library から写真を選択する画面を起動します。

ユーザーがフォトライブラリの写真をタップした時に、25 ~ 34 行目の imagePickerController(_:didFinishPickingMediaWithInfo:) メソッドが実行され、その中で選択された写真を Image Viwer に表示しています。


これで、Swift で画像を Photo Library から選択して表示するコードが書けました。

iOS アプリを iPhone にインストールしてテストする

写真を撮る箇所がシミュレーターでできないので、iPhone にインストールしてテストします。

作った iOS アプリを iPhone にインストールする方法がわからない方は「Xcode からアプリを iPhone にインストールして実行する方法」をご覧ください。


iPhone を指定してこのアプリを実行すると、以下のような画面が表示されるので、Take Photo ボタンをタップします。

Swift - 画像ファイルを写真ライブラリに保存・取得する方法 4


カメラの利用許可を求めるダイアログが表示されるので、OK をタップします。

Swift - 画像ファイルを写真ライブラリに保存・取得する方法 5


カメラが起動するので、写真を撮ります。

Swift - 画像ファイルを写真ライブラリに保存・取得する方法 6


この写真でよければ、Use Photo をタップします。撮り直したい時は Retake をタップして撮り直してください。

Swift - 画像ファイルを写真ライブラリに保存・取得する方法 7


Use Photo をタップすると、カメラが閉じ、元の画面に戻って、撮った写真が画面に表示されるので、Save to Photo Library をタップして写真を保存します。

Swift - 画像ファイルを写真ライブラリに保存・取得する方法 8


アプリをインストールしてはじめて、Photo Library にアクセスしようとした時に、利用許可を求めるダイアログが表示されるので、OK をタップします。

Swift - 画像ファイルを写真ライブラリに保存・取得する方法 9


Xcode の output window に Photo saved successfully. と表示され、写真アプリを開くとこの画像が入っています。

Swift - 画像ファイルを写真ライブラリに保存・取得する方法 10


Clear Photo ボタンをタップして、Image View の画像を一旦削除します。

Swift - 画像ファイルを写真ライブラリに保存・取得する方法 11


Select from Photo Library ボタンをタップすると、Photo Library の写真が表示されます。

Swift - 画像ファイルを写真ライブラリに保存・取得する方法 12


Photo Library の写真をタップすると、画面が閉じ、元の画面の UIImageView に選択した画像が表示されます。

Swift - 画像ファイルを写真ライブラリに保存・取得する方法 13

Swift - 画像ファイルを写真ライブラリに保存・取得する方法 14


ちなみに、何度も Save to Photo Library ボタンをタップすると、その数だけ画像が Photo Library に保存されます。


以上、Swift で画像ファイルを写真ライブラリ (Photo Library) に保存・取得する方法をご説明しました。

© 2024 iOS 開発入門