포스트

단어장 프로젝트 (11)

iCloud에서 데이터 가져왔을때의 문제 해결

1. 기존데이터와 중복되는 경우

이건 근본적으로 코어데이터의 중복을 피하기위해

클라우드에 데이터를 저장할때 uuid를 넣어 데이터의 무결성을 지키기 위해 사용이 되는데

코어데이터 등록할때는 해당 부분이 없어서 생긴 문제이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//단어 저장
    func saveWord(word: String, definition: String, detail: String, pronunciation: String, synonym: String, antonym: String, to bookCase: BookCase, to bookCaseName: String, errorHandler: @escaping (Error) -> Void) {
        guard let context = managedContext else {
            print("Error: managedContext is nil")
            return
        }
        
        let newWord = WordEntity(context: context)
        newWord.uuid = UUID().uuidString // added
        newWord.word = word
        newWord.definition = definition
        newWord.detail = detail
        newWord.pronunciation = pronunciation
        newWord.synonym = synonym
        newWord.antonym = antonym
        newWord.date = Date()
        newWord.memory = false
        
        newWord.bookCase = bookCase
        newWord.bookCaseName = bookCase.name
        
        do {
            try context.save()
            print("단어가 저장되었습니다.")
        } catch let error as NSError {
            errorHandler(error)
        }
    }

//단어장 추가
    func saveBookCase(name: String, explain: String, word: String, meaning: String, image: Data, errorHandler: @escaping (Error) -> Void) {
        guard let context = managedContext else {
            print("Error: managedContext is nil")
            return
        }
        
        let entity = NSEntityDescription.entity(forEntityName: "BookCase", in: context)!
        let bookCase = NSManagedObject(entity: entity, insertInto: context)
        
        bookCase.setValue(UUID().uuidString, forKey: "uuid") // added
        bookCase.setValue(name, forKey: "name")
        bookCase.setValue(explain, forKey: "explain")
        bookCase.setValue(word, forKey: "word")
        bookCase.setValue(meaning, forKey: "meaning")
        bookCase.setValue(image, forKey: "image")
        
        do {
            try context.save()
            print("코어데이터가 저장되었습니다.")
        } catch let error as NSError {
            errorHandler(error)
        }
    }

이렇게 코어데이터에 추가할때 바로 uuid를 추가하게 해주었다.

이로써 코어데이터에 저장되는 데이터도 무결성을 가지게 된다.

2. 클라우드에서 불러온 단어장 삭제시 단어장만 삭제되는 문제 해결

기능을 구현한 팀원분께 여쭤보니 cascade를 통해 해당 애초에 코어데이터 모델링을 하면서 해당 방식이 적용이 되어 로컬에서는 그방식이 채택이 되어있는지

그기능이 작동하여 문제없이 삭제가 되었으나,

클라우드에서 복원한 데이터는 그런 기능이 없다.

그래서 데이터 삭제할때 entity에 접근하여 삭제를 하는 코드를 작성했다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//단어장 삭제
    func deleteBookCase(bookCase: NSManagedObject, errorHandler: @escaping (Error) -> Void) {
        // 단어장 삭제
        managedContext?.delete(bookCase)
        
        // 해당 단어장과 관련된 단어 삭제
        guard let bookname = bookCase as? BookCase else {
            return
        }
        
        let request: NSFetchRequest<WordEntity> = WordEntity.fetchRequest()
        let predicate = NSPredicate(format: "bookCaseName == %@", bookname.name!)
        request.predicate = predicate
        
        do {
            
            let words = try managedContext!.fetch(request)
            for word in words {
                managedContext!.delete(word)
            }
            try managedContext?.save()
        } catch let error as NSError {
            errorHandler(error)
        }
    }

해결.

iCloud 데이터 삭제

지금은 CRUD중

CRU만 될것이다.

이제 D를 구현해본다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
func deleteAllRecordsFromCloudKit(recordType: String) {
        let database = CKContainer(identifier: "iCloud.com.teamproject.Vocabularytest").privateCloudDatabase
        let query = CKQuery(recordType: recordType, predicate: NSPredicate(value: true))
        
        database.perform(query, inZoneWith: nil) { records, error in
            if let error = error {
                print("Error fetching records from CloudKit: \(error)")
                return
            }
            
            guard let records = records else { return }
            
            let recordIDs = records.map { $0.recordID }
            let operation = CKModifyRecordsOperation(recordsToSave: nil, recordIDsToDelete: recordIDs)
            
            operation.modifyRecordsCompletionBlock = { savedRecords, deletedRecordIDs, operationError in
                if let operationError = operationError {
                    print("Error deleting records: \(operationError)")
                } else {
                    print("\(deletedRecordIDs?.count ?? 0) records deleted from CloudKit")
                }
            }
            
            database.add(operation)
        }
    }

    func deleteAllCloudKitData() {
        deleteAllRecordsFromCloudKit(recordType: "BookCase")
        deleteAllRecordsFromCloudKit(recordType: "WordEntity")
    }

완료

앞으로도 보강할게 많다.

그만큼 더 공부해야한다는 뜻.

벌써부터 신나네

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.