実現したいこと
献立アプリを作っています。
Core Dataを使用してユーザーがデータベースに料理のメニューを追加でき、またデータベースから料理の情報を取り出してリストに表示できるようにしたいです。
保存、表示したい情報としてはname/sort/time/calorie/image/videoがあります。
発生している問題・分からないこと
AddRecipeViewで、videoの選択はできるのですが、再度開いた時に保存されていない、もしくは保存はされているが表示されないという状態です。
該当のソースコード
AddRecipeView.swift
1import SwiftUI 2 3struct AddRecipeView: View { 4 @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode> 5 @Environment(\.managedObjectContext) private var viewContext 6 @EnvironmentObject var dateHolder: DateHolder 7 8 @State var selectedRecipe: Menu? 9 @State var name: String 10 let sorts = ["", "PASTA & RICE", "MEAT & FISH", "SALAD", "SOUP"] 11 @State private var sortNo = 1 12 @State private var time = 0 13 @State private var calorie = "" 14 @State private var selectedImage: UIImage? 15 @State private var isShowingImagePicker = false 16 @State private var selectedVideoURL: URL? 17 @State private var isShowingVideoPicker = false 18 19 init(alreadyMadeMenu: Menu?) { 20 if let menu = alreadyMadeMenu { 21 _selectedRecipe = State(initialValue: menu) 22 _name = State(initialValue: menu.name ?? "") 23 _sortNo = State(initialValue: Int(menu.sortNo?.sortNo ?? 0)) 24 _time = State(initialValue: Int(menu.time)) 25 _calorie = State(initialValue: menu.calorie ?? "") 26 _selectedImage = State(initialValue: menu.selectedImage.flatMap { UIImage(data: $0) }) 27 if let videoURL = menu.selectedVideoURL as? URL { 28 _selectedVideoURL = State(initialValue: videoURL) 29 } else { 30 _selectedVideoURL = State(initialValue: nil) 31 } 32 } else { 33 _name = State(initialValue: "") 34 _sortNo = State(initialValue: 0) 35 _time = State(initialValue: 0) 36 _calorie = State(initialValue: "") 37 _selectedImage = State(initialValue: UIImage()) 38 _selectedVideoURL = State(initialValue: URL(string: "")) 39 } 40 } 41 var body: some View { 42 Form { 43 Section(header: Text("Menu")){ 44 TextField("料理名", text: $name) 45 Picker("種類を選択", selection: $sortNo) { 46 ForEach(0 ..< sorts.count, id: \.self) { num in 47 Text(self.sorts[num]) 48 } 49 } 50 HStack { 51 Text("調理時間") 52 Spacer() 53 Picker("", selection: $time) { 54 ForEach(1 ..< 91, id: \.self) { num in 55 Text("\(num)分") 56 } 57 } 58 } 59 TextField("カロリー", text: $calorie) 60 VStack { 61 HStack { 62 Text("Photo") 63 .font(.title3) 64 Spacer() 65 } 66 Spacer() 67 HStack { 68 if let image = selectedImage { 69 Image(uiImage: image) 70 .resizable() 71 .aspectRatio(contentMode: .fit) 72 .frame(width: 200, height: 200) 73 } else { 74 Text("写真が選択されていません") 75 } 76 Spacer() 77 Button("写真を選択") { 78 // ボタンがタップされたときに画像選択UIを表示する 79 isShowingImagePicker.toggle() 80 } 81 } 82 .sheet(isPresented: $isShowingImagePicker) { 83 // 画像選択UIを表示する 84 ImagePicker(image: $selectedImage) 85 } 86 } 87 VStack { 88 HStack { 89 Text("Video") 90 .font(.title3) 91 Spacer() 92 } 93 Spacer() 94 HStack { 95 if let videoURL = selectedVideoURL { 96 Text("Selected Video: \(videoURL.lastPathComponent)") 97 } else { 98 Text("ビデオが選択されていません") 99 } 100 Spacer() 101 Button("ビデオを選択") { 102 // ボタンがタップされたときに動画選択UIを表示する 103 isShowingVideoPicker.toggle() 104 } 105 } 106 .sheet(isPresented: $isShowingVideoPicker) { 107 // 動画選択UIを表示する 108 DocumentPicker(url: $selectedVideoURL) 109 } 110 } 111 } 112 Section() { 113 Button("Save", action: saveAction) 114 .font(.headline) 115 .frame(maxWidth: .infinity, alignment: .center) 116 } 117 } 118 } 119 func saveAction() { 120 withAnimation { 121 if selectedRecipe == nil { 122 selectedRecipe = Menu(context: viewContext) 123 } 124 selectedRecipe?.created = Date() 125 selectedRecipe?.name = name 126 selectedRecipe?.time = Double(time) 127 selectedRecipe?.calorie = calorie 128 if let selectedImage = selectedImage { 129 if let imageData = selectedImage.jpegData(compressionQuality: 1.0) { 130 selectedRecipe?.selectedImage = imageData 131 } 132 } 133 selectedRecipe?.selectedVideoURL = selectedVideoURL?.absoluteString 134 // Sortエンティティのインスタンスを取得する 135 let sort = Sort(context: viewContext) 136 sort.sortNo = Int64(sortNo) 137 // selectedRecipeのsortNoプロパティにSortエンティティを代入する 138 selectedRecipe?.sortNo = sort 139 140 dateHolder.saveContext(viewContext) 141 self.presentationMode.wrappedValue.dismiss() 142 } 143 } 144} 145 146struct AddRecipeView_Previews: PreviewProvider { 147 static var previews: some View { 148 AddRecipeView(alreadyMadeMenu: Menu()) 149 } 150} 151
DateHolder.swift
1import Foundation 2import CoreData 3 4class DateHolder: ObservableObject { 5 init(_ context: NSManagedObjectContext) { 6 7 } 8 9 func saveContext(_ context: NSManagedObjectContext) { 10 do { 11 try context.save() 12 } catch { 13 let nsError = error as NSError 14 fatalError("Unresolved error \(nsError), \(nsError.userInfo)") 15 } 16 } 17}
DocumentPicker.swift
1import SwiftUI 2import MobileCoreServices 3 4struct DocumentPicker: UIViewControllerRepresentable { 5 @Binding var url: URL? 6 @Environment(\.presentationMode) var presentationMode 7 8 class Coordinator: NSObject, UIDocumentPickerDelegate { 9 let parent: DocumentPicker 10 11 init(parent: DocumentPicker) { 12 self.parent = parent 13 } 14 15 func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { 16 guard let url = urls.first else { return } 17 parent.url = url 18 parent.presentationMode.wrappedValue.dismiss() 19 } 20 21 func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) { 22 parent.presentationMode.wrappedValue.dismiss() 23 } 24 } 25 26 func makeCoordinator() -> Coordinator { 27 Coordinator(parent: self) 28 } 29 30 func makeUIViewController(context: Context) -> UIDocumentPickerViewController { 31 let picker = UIDocumentPickerViewController(documentTypes: [String(kUTTypeMovie)], in: .open) 32 picker.delegate = context.coordinator 33 return picker 34 } 35 36 func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: Context) {} 37} 38
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
以下のようなデバック出力を追加してみましたが、 selectedRecipe?.selectedVideoURL は正しく設定されているようでした。
AddRecipeView.swift
1print("selectedVideoURL: \(selectedVideoURL)") 2print("selectedRecipe?.selectedVideoURL: \(selectedRecipe?.selectedVideoURL)") 3selectedRecipe?.selectedVideoURL = selectedVideoURL?.absoluteString 4print("After assignment:") 5print("selectedRecipe?.selectedVideoURL: \(selectedRecipe?.selectedVideoURL)")
AddRecipeView.swift
1selectedRecipe?.selectedVideoURL = selectedVideoURL?.absoluteString 2print("selectedVideoURL: \(selectedVideoURL?.absoluteString ?? "nil")") 3print("selectedRecipe?.selectedVideoURL: \(selectedRecipe?.selectedVideoURL ?? "nil")")
補足
Xcode version14.2
回答にあたり必要な情報があれば伝えていただきたいです。
お分かりになる方、回答よろしくお願いします。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2024/02/14 13:02
2024/02/14 23:07