[iOS] App Development

[iOS] 다이어리 앱 개발 : 테이블뷰에서 선택한 Row의 파이어스토어 문서 documentID값 아는법, 주의할 점

ddgoori 2021. 12. 27. 00:31

테이블뷰에서 선택한 Row의 파이어스토어 문서 documentID값 아는법

 

=> Diary Struct에 documentID값 필드를 추가해서 문서를 생성할 때 documentID값을 필드에 추가해준다. 추가시(addDocuemt)에 자동으로 생선된 documentID값이 있는데 성공적으로 추가 됐을 경우 필드에 해당값을 추가하면 된다.

 

이를 데이터 조회(get)해올 때 받아올때 같이 받아와서 배열에 넣어주면 didSelectRow에서 선택한 indexPath.row를 통해 배열의 한 element의 필드값으로 이전에 생성하며 미리 저장해두고, get해온 documentID값을 불러와서 수정하면된다. 소스코드를 보며 이해할 수 있도록 프로젝트 하며 작성한 코드를 공유해본다.

 

먼저,  1) 데이터 받아오는 모델 구조에 documentID필드가 필요하니 추가하고

struct Diary {
    var content: String
    var timeStamp: Date
    var emoji: String
    var documentId: String
    
    // Key(Strin(g)-Value(Any)
    var dictionary: [String:Any] {
        return [
            "content": content,
            "timeStamp": timeStamp,
            "emoji": emoji,
            "documentId": documentId
        ]
    }
}

 

 

가져오기 위해선 문서가 먼저 생성되어있어야 하기 때문에 새로운 다이어리 글 작성할 때 2) addDocument함수로 먼저 난수로 documentID값이 생성되어있어야 한다. (새로운 다이어리를 작성하고 Save버튼을 눌렀을 때 실행되는 함수)

self.ref = self.db
                .collection("Diaries").document(self.userUid!)
                .collection("Diary").addDocument(data: newDiary.dictionary)

 

 

3) 생성이 성공하면 받아온 id값으로 필드값에 추가해준다. (새로운 다이어리를 작성하고 Save버튼을 눌렀을 때 실행되는 함수)

          self.ref = self.db
                .collection("Diaries").document(self.userUid!)
                .collection("Diary").addDocument(data: newDiary.dictionary) { err in
                    if let err = err {
                        print("Error adding document: \(err)")
                    } else {
                        print("Document added with ID: \(self.ref!.documentID)")
                        
                        self.db.collection("Diaries").document(self.userUid!)
                            .collection("Diary").document(self.ref!.documentID).updateData([
                                "documentId": self.ref!.documentID
                            ]) { err in
                                if let err = err {
                                    print("Error writing document: \(err)")
                                } else {
                                    print("Document ID successfully added!")
                                }
                                
                            }
                    }

 

 

필드값에 실제 난수로 생성된 documentId가 성공적으로 추가되는 것을 알 수 있다.

 

 

 

4) 이를 get데이터해올때 가져온다. document객체에서 아이디값을 물고있기 때문에 쉽게 가져올 수 있다. 

 func loadDiaryData() {
        db.collection("Diaries").document(userUid!)
            .collection("Diary").getDocuments() { (querySnapshot, err) in
                if let err = err {
                    print("Error getting documents: \(err)")
                } else {
                    for document in querySnapshot!.documents {
                        print("\(document.documentID) => \(document.data())")
                        if let stamp = document.data()["timeStamp"] as? Timestamp {
                            self.diaryArray.append(Diary(content: document.data()["content"] as! String, timeStamp: stamp.dateValue() as! Date, emoji: document.data()["emoji"] as! String, documentId: document.data()["documentId"] as! String))
                        }
                    }
                    DispatchQueue.main.async {
                        self.tableView.reloadData()
                    }
                }
            }
    }

 

5) 이렇게 불러와진 데이터를 diaryArray에 넣고, didSelectRow했을 때 해당행의 documentID값을 통해 문서에 접근하여 데이터를 변경하거나 삭제할 수 있다. 

 

 

그리고 주의점 setData를 할 경우에 아예 새로 써지기 때문에 기존에 추가된 필드도 사라진다.

6) updateData함수를 이용해서 전체 덮어쓰기가 아닌 일부필드만 업데이트 하도록 한다.

  
            self.db.collection("Diaries").document(self.userUid!)
                .collection("Diary").document(diary.documentId).updateData([
                    "content": note
                ]) { err in
                    if let err = err {
                        print("Error writing document: \(err)")
                    } else {
                        print("Document successfully modified!")
                    }
                    
                }

 

수정 전 데이터

 

수정 후 데이터

 

데이터가 정상적으로 업데이트 되는 것을 확인할 수 있다.

 

핵심은 다이어리 구조체에 documentId를 추가하고, 문서가 성공적으로 생성됐을 때 파이어스토어의 documentId 값으로 문서를 타고들어가 구조체 필드에 성공한 ref!.documentID 값을 업데이트 시키는 것이다. 그리고 viewDidLoad()에서 이렇게 만들어진 데이터들을 배열에 가져와 담고, indexPath.Row를 통해 선택한 배열의 indexPath.Row번째 값의 documentID값을 가져와서 이용하면된다.

선택한 배열의 요소, 즉 테이블뷰 셀의 documentID값을 알아야 수정된 문서 데이터를 다시 update쳐서 반영할 수 있기 때문에 documentID값을 아는 것은 중요하고, 스택오버 플로우에도 이에 대한 질문이 많았다.