💨

(iOS)写真アプリのキャプションを編集する方法

に公開

結論

お急ぎの方のため結論から。

  • Photosフレームワークに写真のキャプションを編集する機能はありません。
  • 写真アプリにおけるキャプションはEXIFのImage Descriptionタグの値を参照しています。
  • Image I/Oフレームワークを利用してEXIFのImage Descriptionタグの値を読み書きすることは可能です。

実装例

参考までに、指定されたファイルのImage Descriptionを上書きする処理を示します。

import Foundation
import ImageIO
import UniformTypeIdentifiers

func writeExifImageDescription(inputFile: URL, imageDescription: String) {
  guard let source = CGImageSourceCreateWithURL(inputFile as CFURL, nil) else {
    return
  }
  guard let metadata = CGImageSourceCopyPropertiesAtIndex(source, 0, nil) as? [String: Any] else {
    return
  }

  var mutableMetadata = metadata

  if var tiff = mutableMetadata[kCGImagePropertyTIFFDictionary as String] as? [String: Any] {
    tiff[kCGImagePropertyTIFFImageDescription as String] = imageDescription as CFString
    mutableMetadata[kCGImagePropertyTIFFDictionary as String] = tiff
  } else {
    mutableMetadata[kCGImagePropertyTIFFDictionary as String] = [
      kCGImagePropertyTIFFImageDescription as String: imageDescription as CFString
    ]
  }
  guard let cgImage = CGImageSourceCreateImageAtIndex(source, 0, nil) else {
    return
  }

  let typeIdentifier: String
  let fileExtension = inputFile.pathExtension.lowercased()

  if let inputUTI = UTType(filenameExtension: fileExtension)?.identifier {
    typeIdentifier = inputUTI
  } else {
    typeIdentifier = UTType.jpeg.identifier
  }
  guard
    let destination = CGImageDestinationCreateWithURL(
      inputFile as CFURL, typeIdentifier as CFString, 1, nil)
  else {
    return
  }

  CGImageDestinationAddImage(destination, cgImage, mutableMetadata as CFDictionary)
  CGImageDestinationFinalize(destination)
}

例えばキャプションつきの画像を写真アプリに作成する場合、Image Descriptionを書き込んだ後にPHAssetChangeRequest.creationRequestForAssetFromImage(atFileURL: inputFile)を実行します。

(余談)VoiceOverスクリーンリーダーの挙動

キャプションつき画像をPHAssetChangeRequest.creationRequestForAssetFromImage経由で作成すると、写真のアクセシビリティラベルにその内容が反映されます。iOS 15からiOS 18の実機で確認済みです。

一方、写真アプリを開き画像を選択して、情報メニューからキャプションを編集してもアクセシビリティラベルには内容が反映されません。VoiceOverは「写真」としか読み上げしません。

Discussion