ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Swift iOS: 이미지를 불러오는 Action Extension(액션 확장)에서 스크린샷 이미지를 인식하지 못하는 문제 해결 방법
    공부/Swift(프로그래밍 언어) 2026. 2. 8. 19:29
    반응형

    문제

    • 이미지를 불러오는 Action Extension 코드가 있음
    • 다른 경우는 전부 이미지를 불러올 수 있는데 특정 케이스에서는 이미지를 불러오지 못함 
      • 예) 스크린샷 직후 공유 메뉴를 실행했을 때

    기존 코드

    import UIKit
    import SwiftUI
    import MobileCoreServices
    import UniformTypeIdentifiers
    
    class ActionViewController: UIViewController {
      // ... //
    
      private func handleInputImage() {
        guard let extensionItem = extensionContext?.inputItems.first as? NSExtensionItem else { return }
        guard let attachments = extensionItem.attachments else { return }
    
        for provider in attachments {
          if provider.hasItemConformingToTypeIdentifier(UTType.image.identifier) {
            provider.loadItem(forTypeIdentifier: UTType.image.identifier, options: nil) { item, error in
              if let error {
                print("이미지 로드 오류:", error)
                return
              }
    
              var image: UIImage?
    
              if let url = item as? URL {
                if let data = try? Data(contentsOf: url) {
                  image = UIImage(data: data)
                }
              } else if let uiImage = item as? UIImage {
                image = uiImage
              }
    
              DispatchQueue.main.async {
                // self.showSwiftUI(with: image)
                let red = UIView()
                red.backgroundColor = .red
                self.view.addSubview(red)
                if let image {
                  self.saveImageToAppGroup(image)
                }
              }
            }
          }
        }
      }
    
      // ... //
    }

     

    해결 방법

    스크린샷으로 찍은 저장 전 화면이 Action Extension에서 안 읽히는 이유는, 이 경우 이미지가 파일(URL)이나 UIImage가 아니라 in-memory PNG/JPEG Data 형태로 전달되는 경우가 많기 때문입니다.

     

    핵심 원인

    • 사진 앱에 저장된 이미지 → URL 또는 UIImage로 전달되는 경우가 많음
    • 스크린샷 직후 공유(저장 전) → UTType.image는 매칭되지만 실제 item은 Data (PNG/JPEG) 형태로 전달되는 경우가 있음
    • 기존 코드에서는 URL, UIImage만 처리 → 스크린샷 누락

     

    변경 코드

      private func handleInputImage() {
        guard let extensionItem = extensionContext?.inputItems.first as? NSExtensionItem else { return }
        guard let attachments = extensionItem.attachments else { return }
    
        for provider in attachments {
          if provider.hasItemConformingToTypeIdentifier(UTType.image.identifier) {
            provider.loadItem(forTypeIdentifier: UTType.image.identifier, options: nil) { item, error in
              if let error {
                print("이미지 로드 오류:", error)
                return
              }
    
              var image: UIImage?
              var message: String = "이미지 로드 실패"
    
              if let url = item as? URL {
                if let data = try? Data(contentsOf: url),
                   let loadedImage = UIImage(data: data) {
                  image = loadedImage
                  message = "URL 기반 이미지 로드"
                } else {
                  message = "URL은 있으나 이미지 데이터 변환 실패"
                }
              } else if let uiImage = item as? UIImage {
                image = uiImage
                message = "UIImage 형태로 로드"
              // ⬇️⬇️⬇️ item이 데이터인 경우 추가 
              } else if let data = item as? Data,
                        let loadedImage = UIImage(data: data) {
                image = loadedImage
                message = "Data 형태로 로드 (스크린샷 가능)"
              }
    
              DispatchQueue.main.async {
                self.showSwiftUI(with: image, message: message)
              }
            }
          // ⬇️⬇️⬇️ PNG 메모리 데이터 부분 추가
          } else if provider.hasItemConformingToTypeIdentifier(UTType.png.identifier) {
            provider.loadDataRepresentation(forTypeIdentifier: UTType.png.identifier) { data, error in
              if let data,
                 let image = UIImage(data: data) {
                DispatchQueue.main.async {
                  self.showSwiftUI(with: image, message: "PNG Data로 스크린샷 로드")
                }
              }
            }
          }
        }
      }

    적용한 해결 방식 (패치 내용 요약)

    1. item as? Data 처리 추가
      • UIImage(data:)로 변환
      • 스크린샷 Data 케이스 대응
    2. UTType.png에 대한 별도 분기
      • loadItem 대신 loadDataRepresentation(forTypeIdentifier:) 사용
      • 저장 전 스크린샷에서 가장 안정적인 방식

    이렇게 하면 대부분의 케이스가 모두 커버됩니다.

     

    왜 loadDataRepresentation이 중요한가

    • Action Extension은 다른 앱의 메모리 버퍼를 직접 받는 구조
    • 스크린샷은 아직 파일 시스템에 없을 수 있음
    • 이 경우 URL이 아예 존재하지 않음
    • Apple도 이미지 공유 확장에서는 Data 기반 처리를 권장하는 편입니다

     

    실무 팁

    • 이미지 공유 Extension에서는
      • URL
      • UIImage
      • Data
        세 가지를 항상 모두 처리하는 것이 안전합니다.

    추가로:

    • HEIC (UTType.heic)
    • JPEG (UTType.jpeg)
      까지 커버하고 싶으시면 동일 패턴으로 확장 가능합니다.

     

     

    반응형
Designed by Tistory.