Trouble shooting

AutoLayout

storyboard IDλ₯Ό 섀정해도 idλ₯Ό 찾을 수 μ—†λ‹€λŠ” μ—λŸ¬κ°€ λ°œμƒν•¨.

Storyboard doesn't contain a view controller with identifier "ChattingViewController"

상황 μ„€λͺ…

  1. Main View Controllerμ—μ„œ Sign In λ²„νŠΌμ„ ν΄λ¦­ν•˜λ©΄, ChattingViewControllerκ°€ λ‚˜μ™€μ•Όν•¨.

  2. ChattingViewController μ„€μ •

  3. λ‚΄κ°€ μž‘μ„±ν•œ μ½”λ“œ

    @IBAction func didTappedSignInButton(_ sender: UIButton) {
        
        guard let email = emailTextField.text,
              let password = passwordTextField.text else { return }
        
        Auth.auth().signIn(withEmail: email, password: password) { [weak self] result, error in
            guard let strongSelf = self else { return }
            
            if let error { return }
            guard let viewController = self?.storyboard?.instantiateViewController(withIdentifier: "ChattingViewController") as? ChattingViewController else { return }
            self?.present(viewController, animated: true, completion: nil)
        }
    }

원인과 ν•΄κ²°κ³Όμ •

Main.storyboardμ—μ„œ storyboardλ₯Ό κ΄€λ¦¬ν•˜μ§€ μ•Šκ³ , storyboard referenceλ₯Ό μ‚¬μš©ν•˜κ³  μžˆμ—ˆλ‹€.

그런데 ν•΄λ‹Ή referenceλ₯Ό μ„ μ–Έν•΄μ£Όμ§€ μ•Šμ•„μ„œ self.storyboardμ—μ„œ ν•΄λ‹Ή IDλ₯Ό 찾을 수 μ—†λ˜ κ²ƒμ΄μ—ˆλ‹€.

κ·Έλž˜μ„œ storyboard referenceλ₯Ό λ‹€μ‹œ μ„ μ–Έν•΄μ„œ 문제λ₯Ό ν•΄κ²°ν–ˆλ‹€. (push둜 λ³΄μ—¬μ€¬λ˜ 연결을 끊고 μ‚­μ œν–ˆμ—ˆλ‹€)

μΆ”κ°€. μƒˆλ‘œμš΄ λ„€λΉ„κ²Œμ΄μ…˜μœΌλ‘œ μ΄λ™ν•˜λŠ” 방법

    // MARK: function
    private func moveUserListViewController() {
        let storyboard = UIStoryboard(name: "UserList", bundle: nil)
        let viewController = storyboard.instantiateViewController(withIdentifier: "UserList") as! UserListViewController
        let navigationController = UINavigationController(rootViewController: viewController)
        navigationController.modalPresentationStyle = .fullScreen
        
        self.present(navigationController, animated: true, completion: nil)
    }
    
    // MARK: IBAction
    @IBAction func didTappedSignInButton(_ sender: UIButton) {
        
        guard let email = emailTextField.text,
              let password = passwordTextField.text else { return }
        
        Auth.auth().signIn(withEmail: email, password: password) { [weak self] result, error in
            guard let strongSelf = self else { return }
            
            if let error {
                let alert = UIAlertController(title: "였λ₯˜", message: "였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.", preferredStyle: .alert)
                return
            }
            self?.moveUserListViewController()
        }
    }

Firestore

FIRInvalidArgumentException', reason: 'Unsupported type: __SwiftValue

  • μ±„νŒ… 방을 μƒμ„±ν•˜κΈ° μœ„ν•΄, μ°Έμ—¬μžλ₯Ό κΈ°μ€€μœΌλ‘œ ν˜„μž¬ μ±„νŒ… 방이 μ‘΄μž¬ν•˜λŠ”μ§€, μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ”μ§€ ν™•μΈν•˜κΈ° μœ„ν•΄ μ½”λ“œλ₯Ό μž‘μ„±ν–ˆλ‹€.

  • κ·Έλž˜μ„œ users에 [currentUser, tableViewμ—μ„œ μ„ νƒν•œ user]λ₯Ό κΈ°μ€€μœΌλ‘œ chatroom에 μ‘΄μž¬ν•˜λŠ” 방이 μžˆλŠ”μ§€ μ½”λ“œλ₯Ό μž‘μ„±ν–ˆλ‹€.

  • 그런데 FIRInvalidArgumentException', reason: 'Unsupported type: __SwiftValue 이 μ—λŸ¬κ°€ λ°œμƒν•œλ‹€;;

  • κ²°λ‘ : λΉ„μ–΄μžˆλŠ” collection에 μ ‘κ·Όν–ˆκΈ° λ•Œλ¬Έμ΄λ‹€.

    • chatrooms collectionκ³Ό documentsκ°€ λͺ¨λ‘ λΉ„μ–΄μžˆμ—ˆλ‹€.

    • κ·Έλž˜μ„œ λ‚΄κ°€ μ„ μ–Έν•œ codableλŒ€λ‘œ λΉ„μ–΄μžˆλŠ” 데이터 ν•˜λ‚˜λ₯Ό λ§Œλ“€μ–΄μ£Όλ‹ˆ μ‘°νšŒκ°€ 잘 λœλ‹€..... λ‚΄ μ‚½μ§ˆ...

Chat의 λ³€ν™”λ§Œ 감지할 순 μ—†μ„κΉŒ?

μš°μ„  μœ„ μ‚¬μ§„μ—μ„œ λ³Ό 수 μžˆλ“― λ‚˜λŠ” Chat Roomsλ₯Ό Collection으둜 λ§Œλ“€μ—ˆλ‹€. 즉, μ±„νŒ…μ΄ λ³€ν•˜λ©΄, ChatRoom이 λ³€ν•˜κ²Œ λ˜λŠ” 것이고, 그것에 λŒ€ν•œ κ²°κ³Όλ₯Ό 보여쀀 λ‹€λŠ” 것이닀.

이럴 λ•Œ μ–΄λ–€ λ¬Έμ œκ°€ λ°œμƒν•˜λŠλƒ! λ³€κ²½λœ 데이터λ₯Ό κ°€μ Έμ™€μ„œ tableviewλ₯Ό reloadν•΄μ£ΌκΈ° λ•Œλ¬Έμ—, 전체 μ±„νŒ…μ΄ μƒˆλ‘œκ³ μΉ¨λ˜κ²Œ λœλ‹€. (λ°±λ¬ΈλΆˆμ—¬μΌκ²¬ μ˜μƒμ„ 보자)

λ¬Έμ œκ°€ 된 μ˜μƒ

λ¬Έμ œκ°€ 된 μ½”λ“œ

    func setUpDataListener(id: String, completion: @escaping ([Chat]) -> Void) {
        let reference = database.collection("chatRooms").document(id)
        
        reference.addSnapshotListener {document, error in
            guard let document, document.exists,
                  let chatData = document.data()?["chat"] as? [[String: Any]] else {
                print("invalid format")
                return
            }
            
            do {
                let data = try JSONSerialization.data(withJSONObject: chatData, options: [])
                let chats = try JSONDecoder().decode([Chat].self, from: data)
                completion(chats)
            } catch { }
        }
    }

reference인 ChatRooms에 snapshot Listnerλ₯Ό λ‹¬μ•˜λ‹€. κ·Έλž˜μ„œ Chat이 μΆ”κ°€λ˜λ©΄, ChatRoom의 λ³€ν™”κ°€ κ°μ§€λ˜κ³ , κ·Έ κ²°κ³Ό chatData에 ["chat"]으둜 μ˜€λŠ” 값듀이 μΆ”κ°€λ˜κ²Œ λœλ‹€ γ…  γ… 

ν•΄κ²° 방법

쿼리에 listenerλ₯Ό λ‹¬μ•„λ³΄μž -> μ‹€νŒ¨.. (쑰금 더 곡뢀해야겠닀)

listenerλŠ” κ·ΈλŒ€λ‘œ λ‘λ˜, View Controllerμ—μ„œ μƒˆλ‘œμš΄ 데이터λ₯Ό μΆ”μΆœν•˜λŠ” λ°©μ‹μœΌλ‘œ 문제λ₯Ό ν•΄κ²°ν–ˆλ‹€.

  1. κΈ°μ‘΄ μ½”λ“œ

    private func setupChatDataListener() {
        
        guard let chattingRoomID = chattingRoom?.uuid else { return }
        ChatManager.shared.setUpDataListener(id: chattingRoomID) { [weak self] chats in
            for chat in chats {
                self?.chatDatas.append(chat)
                let index = IndexPath(row: (self?.chatDatas.count ?? 0) - 1, section: 0)
                self?.chattingTableView.insertRows(at: [index], with: .bottom)
                self?.chattingTableView.scrollToRow(at: index, at: .bottom, animated: true)
            }
        }
    }

κΈ°μ‘΄ μ½”λ“œμ—μ„œλŠ” μƒˆλ‘œμš΄ 데이터λ₯Ό λͺ¨λ‘ 뢈러였고, κΈ°μ‘΄ Chat dataλ₯Ό μƒˆλ‘œμš΄ λ°μ΄ν„°λ‘œ λ³€κ²½ν•˜λŠ” 방식을 μ‚¬μš©ν–ˆμ—ˆλ‹€. μ˜ˆμ „μ—” λͺ°λžμ§€λ§Œ 이 μ½”λ“œ μ“°λ©΄, A, B, Cκ°€ μžˆμ„ λ•Œ μƒˆλ‘œμš΄ Dκ°€ λ“€μ–΄μ˜¨λ‹€λ©΄ A, B, C, A, B, C, D μ΄λŸ°μ‹μœΌλ‘œ 데이터가 μ±„νŒ…λ°©μ— λ‚¨μ•„μžˆμ—ˆμ„ 것이닀.

  1. μƒˆλ‘œμš΄ μ½”λ“œ

    private func setupChatDataListener() {

        guard let chattingRoomID = chattingRoom?.uuid else { return }
        ChatManager.shared.setUpDataListener(id: chattingRoomID) { [weak self] chats in
            var newChat = [Chat]()
            for chat in chats {
                newChat.append(chat)
            }
            
            newChat = (self?.filterNewChatting(newData: newChat, oldData: self?.chatDatas))!
            
            self?.chatDatas.append(contentsOf: newChat)
            self?.chattingTableView.reloadData()
            
            let index = IndexPath(row: (self?.chatDatas.count ?? 1) - 1, section: 0)
            self?.chattingTableView.scrollToRow(at: index, at: .bottom, animated: true)
            
        }
    }
    
    private func filterNewChatting(newData: [Chat], oldData: [Chat]?) -> [Chat] {
        guard let oldData = oldData else { return [] }
        var newChat = [Chat]()
        
        for chat in newData {
            if !oldData.contains(chat) {
                newChat.append(chat)
            }
        }
        return newChat
    }

κΈ°μ‘΄κ³Ό λ™μΌν•˜κ²Œ Chat Rooms에 μžˆλŠ” λͺ¨λ“  데이터λ₯Ό ν˜ΈμΆœν•˜μ§€λ§Œ, filterNewChattingμ΄λΌλŠ” ν•¨μˆ˜λ₯Ό λ§Œλ“€μ–΄μ„œ κΈ°μ‘΄ μ±„νŒ…μ— μ—†λŠ” μ±„νŒ…λ§Œ κ°€μ Έμ˜€λ„λ‘ μˆ˜μ •ν–ˆλ‹€.

이λ₯Ό μœ„ν•΄μ„œλŠ” Chat λͺ¨λΈμ— Hashable ν”„λ‘œν† μ½œμ„ μ‚¬μš©ν•΄μ•Όν•œλ‹€. (containsλ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄μ„œ)

Last updated