[SwfitUI] fileImporter가 여러개 일때 아래쪽에 선언된 건 트리거 작용해도 동작하지 않는 문제 해결방법
아래 예제 처럼 csv 파일 가져오기와 파일 복원을 개별처리하는 fileImporter가 선언되어 있다.
그런데 isPresented에 트리거 동작을 하는 변수의 값을 true로 변경되어도 파일 찾는 창이 열리지 않는 문제가 발생한다.
// 데이터 복원하기 버튼
Button(action: {
print("[SettingsView] Restore Data button tapped. Current showingFileImporterForRestore: \(showingFileImporterForRestore)")
showingFileImporterForRestore = true // 상태 변수 변경
}) {
HStack {
Image(systemName: "square.and.arrow.down")
.foregroundColor(textColor)
Text("데이터 복원하기")
.foregroundColor(textColor)
}
}
.foregroundColor(.primary) // 버튼 텍스트 색상
// CSV 데이터 가져오기 버튼
Button(action: {
showingFileImporterForCsv = true // CSV 가져오기용 파일 임포터 표시
}) {
HStack {
Image(systemName: "tablecells.badge.ellipsis") // CSV 아이콘 예시
.foregroundColor(textColor)
Text("CSV 데이터 가져오기")
.foregroundColor(textColor)
}
}
.foregroundColor(.primary) // 버튼 텍스트 색상
// --- CSV 파일 가져오기 ---
.fileImporter(isPresented: $showingFileImporterForCsv
, allowedContentTypes: [.commaSeparatedText, .plainText], allowsMultipleSelection: false) { result in
handleFileSelectionForCsv(result)
}
// --- 데이터베이스 파일 복원 ---
.fileImporter(
isPresented: $showingFileImporterForRestore,
// allowedContentTypes: [UTType.data], // 가장 일반적인 타입으로 테스트
allowedContentTypes: [UTType.database, UTType.data, UTType(filenameExtension: "sqlite") ?? UTType.data, UTType(filenameExtension: "db") ?? UTType.data], // 좀 더 다양한 DB 확장자 허용
allowsMultipleSelection: false
) { result in
print("[SettingsView] File importer for restore dismissed. Result: \(result)")
handleFileSelectionForRestore(result)
}
SwiftUI
의 .fileImporter
는 View Modifier로, 한 View에 여러 개를 동시에 붙일 수는 있지만 조건이 충돌되면 맨 위에 선언된 것만 동작하는 문제가 발생할 수 있다. 이건 내부적으로 .sheet
와 비슷한 방식으로 작동하기 때문이다.
문제 요약
.fileImporter
를 두 개 이상 중첩 선언하면,isPresented
조건이 충돌하거나 비슷한 타이밍에 trigger되면 아래쪽 선언이 무시되거나 작동하지 않음.- 특히
.fileImporter
는 내부적으로 **Presentation Modifier (like .sheet)**로 처리되어, 하나만 우선순위에 따라 보이게 됨.
해결 방법
하나의 .fileImporter
에 조건 분기
가장 일반적이고 안정적인 방법은 하나의 .fileImporter
에 분기 처리를 해서 상황에 따라 어떤 파일을 가져올지 결정하는 것이다:
// 하나의 상태 변수로 통합
@State private var currentImportTarget: ImportTarget? = nil
enum ImportTarget {
case csv
case restore
}
// View Modifier
.fileImporter(
isPresented: Binding(
get: { currentImportTarget != nil },
set: { if !$0 { currentImportTarget = nil } }
),
allowedContentTypes: currentImportTarget == .csv
? [.commaSeparatedText, .plainText]
: [.database, .data, UTType(filenameExtension: "sqlite") ?? .data, UTType(filenameExtension: "db") ?? .data],
allowsMultipleSelection: false
) { result in
print("fileImporter result: \(result) for \(String(describing: currentImportTarget))")
switch currentImportTarget {
case .csv:
handleFileSelectionForCsv(result)
case .restore:
handleFileSelectionForRestore(result)
case .none:
break
}
}
swift
// 예: 버튼에서 호출 시
Button("CSV 가져오기") {
currentImportTarget = .csv
}
Button("데이터베이스 복원") {
currentImportTarget = .restore
}
1개로 합쳤더니, 앱 빌드가 안된다. 프리뷰도 계속 무한 루프하다가 타임아웃으로 멈춘다.
.fileImporter를 연속으로 붙여놓지 않고, 떼어 놓았더니 정상동작하네??????? swfitUI 버그인가?
오류 해결
var body: some View {
NavigationStack {
List {
}
.fileImporter( // 하나는 여기에
}
.fileImporter( // 다른 하나는 여기에