Swift UIのListに対するonMoveの不具合

推し活のために、実は家計簿アプリを自作しているんですが、そこである不具合に出会って、無事解決したので、解決法を備忘録として残しておきます。

問題

CoreDataを使って、以下の画像のように日々の買い物の記録をリストにして表示するようにしているのですが、これに順番を変える機能を追加したいと思ったときに不具合に出会いました。

具体的にはList中のあるエンティティ(例えば包丁置き代)を長押しして、例えば上(調整の上)に動かそうとすると、

このように包丁置き代が複製されているように見えてしまうのです。一個の外のViewに戻って、またこのViewに戻ってくると正しく順序が変わった状態になります。

色々試しましたが、結果的には以下のサイトにかかれていることを試したら直りました。

How to correctly manage CoreData i… | Apple Developer Forums
How to correctly manage CoreData i… | Apple Developer Forums

どうやら、CoreDataの要素に対して操作を行う関数はCoreDataのcontextと同じスレッドで動かないといけないらしく、

private func moveCharge(from source: IndexSet, to destination: Int, in section: SectionedFetchResults<String, Charge>.Element) {
        // sourceから移動するChargeを取得
        
        managedObjContext.perform {
            let movingCharge = section[source.first!]
            
            let previousCharge = (destination - 1 >= 0) ? section[destination - 1] : nil
            let nextCharge = (destination < section.count) ? section[destination] : nil
            
            if let prevDate = previousCharge?.date, let nextDate = nextCharge?.date {
                let interval = nextDate.timeIntervalSince(prevDate) / 2
                movingCharge.date = prevDate.addingTimeInterval(interval)
            } else if let prevDate = previousCharge?.date {
                movingCharge.date = prevDate.addingTimeInterval(-1) // 1日後
            } else if let nextDate = nextCharge?.date {
                movingCharge.date = nextDate.addingTimeInterval(1) // 1日前
            }

            // データベースの変更を保存
            DataController.shared.save(context: managedObjContext)
        }
        
    }

managedObjContext.peform { }というので囲ってあげたら、うまく動きました。

← Go home