watari開発 – Advent201923 –

watari開発 – Advent201923 –

stage23: 画像を投稿できるようにする

お次は撮影した画像をlocalに投稿できるようにしよう。

ローカルの画像を表示する

まずは、今リストに表示しているところに選択した画像が出るようにしよう。

先日修正したところを一箇所戻す。

    func makeUIViewController(context: Context) -> UIImagePickerController {
        let imagePickerController = UIImagePickerController()
        imagePickerController.sourceType = .photoLibrary
//        imagePickerController.sourceType = .camera
        imagePickerController.delegate = context.coordinator
        return imagePickerController
    }

こうする。

で、さらに選択後に保存ボタンを押すとCoreDataに保存できるように変更していく

Entitesの追加

file

EntryImage の追加。bodyはbinaryを保存できるようにしておく。(これ多分設計ミスってる気がする。後で直そう。多分 Entryにして全部一つで管理した方が楽)

ImageViewの改修

import CoreData
...
    @Environment(\.managedObjectContext) var managedObjectContext
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
...
            Spacer()
            Button("save image", action: {
                if let image = self.image {
                    let entryImage = EntryImage(context: self.managedObjectContext)
                    entryImage.body = image.pngData()
                    entryImage.createdAt = Date()
                    do {
                        try self.managedObjectContext.save()
                    } catch {
                        print(error)
                    }
                    self.image = nil
                    self.presentationMode.wrappedValue.dismiss()
                }
            })

これで画像を保存することができるようになる。

ContentViewの改修

Listの表示内容を変更する。

// ContentView

...
+    @FetchRequest(fetchRequest: getEntryImages()) var entryImages: FetchedResults<EntryImage>
...
// Listの中に
                    ForEach(self.entryImages, id: \.self) {entryImage in
                        VStack {
                            createImage(entryImage)
                            Text("\(entryImage.createdAt!)")
                        }
                    }.onDelete {indexSet in
                        let deleteEntry = self.entryImages[indexSet.first!]
                        self.managedObjectContext.delete(deleteEntry)

                        do {
                            try self.managedObjectContext.save()
                        } catch {
                            print(error)
                        }
                    }
...
// 最後の方に

func getEntryImages() -> NSFetchRequest<EntryImage> {
    let request: NSFetchRequest<EntryImage> = EntryImage.fetchRequest()
    let sortDescriptor = NSSortDescriptor(key: "createdAt", ascending: true)
    request.sortDescriptors = [sortDescriptor]
    return request
}

func createImage(_ entryImage: NSManagedObject) -> some View {
    if let data = entryImage.value(forKey: "body") as? Data {
        return AnyView(Image(uiImage: UIImage(data: data)!)
            .resizable()
            .aspectRatio(contentMode: .fill)
            .frame(width: 100, height: 100, alignment: .top)
            .clipped()
        )
    } else {
        return AnyView(EmptyView().frame(alignment: .top))
    }
}

これで保存した内容を表示するようになる。

結果

次回は

おそらくアドベントカレンダーの実装系は最後になりそう。
twitterへ画像を投稿してみよう!