피드로 돌아가기
Why @FetchRequest Doesn't Work with Share Extensions (And What Does)
Dev.toDev.to
Mobile

Why @FetchRequest Doesn't Work with Share Extensions (And What Does)

iOS Share Extension가 Core Data 크로스 프로세스 쓰기 시 @FetchRequest 프로퍼티 래퍼가 변경을 감지하지 못해 메인 앱이 앱 재시작까지 데이터 동기화 불가

Kilo Loco2026년 3월 24일8intermediate

Context

메인 앱과 Share Extension이 App Group을 통해 동일한 Core Data SQLite 저장소를 공유할 때 발생하는 문제이다. Share Extension이 데이터를 저장해도 메인 앱의 SwiftUI 리스트는 업데이트되지 않으며, 앱을 강종 후 재시작해야만 새 데이터가 표시된다.

Technical Solution

  • @FetchRequest 프로퍼티 래퍼를 NSFetchedResultsController로 교체: 내부 관찰 메커니즘 대신 수동으로 캐시 초기화 및 재페치 수행
  • 뷰모델에 @Published 배열 추가: NSFetchedResultsController와의 상호작용을 뷰로직에서 분리
  • scenePhase 옵저버 구현: 앱이 foreground로 복귀할 때 reload() 메서드 호출하여 디스크에서 강제 재조회
  • pull-to-refresh 제스처 지원: 사용자가 명시적으로 reload() 트리거 가능하도록 refreshable 수정자 추가
  • NSFetchedResultsControllerDelegate 채택: 동일 프로세스 내 변경사항(swipe-to-delete 등)은 자동으로 감지

Key Takeaway

@FetchRequest는 단일 프로세스 내에서 동일 viewContext를 통한 변경에만 최적화되어 있으며, 크로스 프로세스 SQLite 쓰기는 NSManagedObjectContextObjectsDidChange 알림을 발생시키지 않는다. 따라서 App Group 환경의 Share Extension에서는 reset()과 performFetch()를 통해 캐시를 완전히 무효화하고 디스크에서 재페치하는 접근이 필수이다.


iOS Share Extension과 메인 앱이 App Group 컨테이너의 Core Data를 공유하는 환경에서는 @FetchRequest 대신 NSFetchedResultsController를 사용하고, scenePhase 옵저버에서 reload()로 강제 재페치하면 앱 재시작 없이 크로스 프로세스 데이터 변경을 즉시 반영할 수 있다.

원문 읽기