[Swift] 63 メモアプリ製作 その15 バックアップから復元機能実装

[Mac M2 Pro 12CPU, Ventura 13.6, iOS 17.1.2, Xcode 15.0]

バックアップ用テキストエディタ構造体 Draft2を作成し、失ったメモをクリップボードにコピーできるようにしていましたが、よりスムーズにするため復元ボタンを配置してワンタップで復元できるようにしました。

これでApple Watchでも復元したメモを見ることができます。

import SwiftUI

struct Draft2: View {
    @State var text = ""
    @FocusState var nameFieldIsFocused: Bool
    @Environment(\.managedObjectContext)var viewContext

    var body: some View {
        TextEditor(text:$text)
            .frame(minHeight: 0, maxHeight: .infinity)
            .focused($nameFieldIsFocused)
            .onAppear{
                DispatchQueue.main.asyncAfter(deadline:DispatchTime.now()+0.5){
                    nameFieldIsFocused = true
                }
            }
            .toolbar{
                ToolbarItem(placement:.navigationBarTrailing){
                    if(nameFieldIsFocused){
                        Button(action:{
                            addContent()
                        }){
                            Text("復元")
                            .font(.system(size: 20))
                        }
                    }
                }
            }
    }
    
    func addContent(){
        let newContent = Note(context:viewContext)

        let date = Date()
        newContent.creationDate = date
        newContent.content = text

        // Data Modelを更新
        viewContext.refreshAllObjects()
        
        do{
            try viewContext.save()
            
        }catch{
            fatalError("セーブ失敗")
        }
        nameFieldIsFocused = false
    }
}

[Swift] 62 メモアプリ製作 その14 バックアップ機能実装

[Mac M2 Pro 12CPU, Ventura 13.6, iOS 17.1.2, Xcode 15.0]

Apple Watchで誤ってメモを消してしまうという事故が数ヶ月内で2回発生しました。

対策としてバックアップ機能を新たに実装しました。

メモの保存時にバックアップ用Core Dataにも同じデータを追加するという仕様です。誤って消してしまってもiPhoneの方でバックアップを確認できます。

import SwiftUI

struct Draft: View {
    @State var text = ""
    @FocusState var nameFieldIsFocused: Bool
    @Environment(\.managedObjectContext)var viewContext
    var note: Note?
    var noteBackup: NoteBackup?

    var body: some View {
        TextEditor(text:$text)
            .frame(minHeight: 0, maxHeight: .infinity)
            .focused($nameFieldIsFocused)
            .onAppear{
                DispatchQueue.main.asyncAfter(deadline:DispatchTime.now()+0.5){
                    nameFieldIsFocused = true
                }
            }
            .toolbar{
                ToolbarItem(placement:.navigationBarTrailing){
                    if(nameFieldIsFocused){
                        Button(action:{
                            if note != nil {
                                updateContent(note: self.note!)
                            }else{
                                addContent()
                            }

                        }){
                            Text("更新")
                            .font(.system(size: 20))
                        }
                    }
                }
            }
    }

    func updateContent(note:Note){
        let date = Date()
        note.creationDate = date
        note.content=text
        
        let newContent2 = NoteBackup(context:viewContext)
        newContent2.creationDate = date
        newContent2.content = text

        // Data Modelを更新
        viewContext.refreshAllObjects()
        
        do{
            try viewContext.save()
        }catch{
            fatalError("セーブ失敗")
        }

        nameFieldIsFocused = false
    }

    func addContent(){
        let newContent = Note(context:viewContext)
        let newContent2 = NoteBackup(context:viewContext)

        let date = Date()
        newContent.creationDate = date
        newContent.content = text
        
        newContent2.creationDate = date
        newContent2.content = text

        // Data Modelを更新
        viewContext.refreshAllObjects()
        
        do{
            try viewContext.save()
            
        }catch{
            fatalError("セーブ失敗")
        }

        nameFieldIsFocused = false

    }

}