質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

2858閲覧

Swift FireStoreに保存できない。

atk_721

総合スコア62

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2020/06/23 22:15

前提・実現したいこと

FireStoreにデータを保存したい。
送信ボタンが押された時に、Firestoreに => 送信者のuid/受信者のuid/autoId(自動生成される)/data の様な階層構造で保存したいのですが、
エラーが発生しているのですが、エラーの内容が理解できていません。。。
エラ発生のタイミングはFireStoreにデータを保存するタイミングです。

ドキュメントの参照には偶数のセグメントが必要とあるのですが、そのセグメントはどこで変更するのかわかっていません。

発生している問題・エラーメッセージ

Thread 1: Exception: "FIRESTORE INTERNAL ASSERTION FAILED: Invalid document reference. Document references must have an even number of segments, but messages has 1" FIRESTOREの内部アサーションに失敗しました:無効なドキュメント参照。 ドキュメント参照には偶数のセグメントが必要ですが、メッセージには1つあります

###breakPointでのエラーの箇所

/* * Copyright 2019 Google * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "Firestore/core/src/util/exception_apple.h" #import <Foundation/Foundation.h> #include <exception> #include "Firestore/core/src/util/hard_assert.h" #include "Firestore/core/src/util/string_apple.h" NS_ASSUME_NONNULL_BEGIN namespace firebase { namespace firestore { namespace util { namespace { NSString* ExceptionName(ExceptionType exception) { switch (exception) { case ExceptionType::AssertionFailure: return @"FIRESTORE INTERNAL ASSERTION FAILED"; case ExceptionType::IllegalState: return @"FIRIllegalStateException"; case ExceptionType::InvalidArgument: return @"FIRInvalidArgumentException"; } UNREACHABLE(); } NSException* MakeException(ExceptionType type, const std::string& message) { return [[NSException alloc] initWithName:ExceptionName(type) reason:MakeNSString(message) userInfo:nil]; } } // namespace ABSL_ATTRIBUTE_NORETURN void ObjcThrowHandler(ExceptionType type, const char* file, const char* func, int line, const std::string& message) { if (type == ExceptionType::AssertionFailure) { [[NSAssertionHandler currentHandler] handleFailureInFunction:MakeNSString(func) file:MakeNSString(file) lineNumber:line description:@"%@: %s", ExceptionName(type), message.c_str()]; std::terminate(); } else { @throw MakeException(type, message); // NOLINT //⇦ここでエラーが出る。 } } } // namespace util } // namespace firestore } // namespace firebase NS_ASSUME_NONNULL_END

該当のソースコード

###ChatViewController

extension ChatController: CustomInputViewDelegate { func inputView(_ inputView: CustomInputAccessoryView, wantsToSend message: String) { Service.uploadMessage(message, to: user) { (error) in if let error = error { print("DEBUG: failed to upload message with error (error.localizedDescription)") return } inputView.cleraMessageText() } } }

customInputView内のsendButtonが有り、押されるとdelgateでChatViewControllerにmessageが入ってきます。

Service.swift

struct Service { static let shared = Service() static func fetchUsers(completion: @escaping([User], Error?) -> Void) { var users = [User]() Firestore.firestore().collection("users").getDocuments { (snapShot, error) in if let error = error { completion(users,error) return } guard let snapShot = snapShot else{ completion(users,error) return } snapShot.documents.forEach { (document) in let dictionary = document.data() let user = User(dictionary: dictionary as [String: AnyObject]) users.append(user) } completion(users, nil) } }   //⇩ static func uploadMessage(_ message: String, to user: User, completion: ((Error?) -> Void)?) { guard let currentUid = Auth.auth().currentUser?.uid else {return} let data = ["message": message, "fromId": currentUid, "toId": user.uid, "timestamp": Timestamp(date: Date())] as [String: Any] COLLECTION_MESSAGES.document(currentUid).collection(user.uid).addDocument(data: data) { _ in COLLECTION_MESSAGES.document(user.uid).collection(currentUid).addDocument(data: data, completion: completion) } } }

###customInputAccesorryView

import UIKit protocol CustomInputViewDelegate: class{ func inputView(_ inputView: CustomInputAccessoryView, wantsToSend message: String) } class CustomInputAccessoryView: UIView { //MARK: - Properties weak var delegate: CustomInputViewDelegate? internal let messageInputTextView: UITextView = { let tv = UITextView() tv.font = UIFont.systemFont(ofSize: 16) tv.isScrollEnabled = false tv.backgroundColor = .clear tv.textColor = .black return tv }() private let sendButton: UIButton = { let button = UIButton(type: .system) button.setTitle("Send", for: .normal) button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 14) button.setTitleColor(.systemPurple, for: .normal) button.addTarget(self, action: #selector(handleSendMessage), for: .touchUpInside) return button }() private let placeHolderLabel: UILabel = { let label = UILabel() label.text = "Enter Message" label.font = UIFont.systemFont(ofSize: 16) label.textColor = .lightGray return label }() //MARK: - View LifeCycle override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .white autoresizingMask = [.flexibleHeight] layer.shadowOpacity = 0.25 layer.shadowRadius = 10 layer.shadowOffset = .init(width: 0, height: -8) layer.shadowColor = UIColor.lightGray.cgColor addSubview(sendButton) sendButton.anchor(top: topAnchor, right: rightAnchor, paddingTop: 4, paddingRight: 8) sendButton.setDimensions(height: 50, width: 50) addSubview(messageInputTextView) messageInputTextView.anchor(top: topAnchor, left: leftAnchor, bottom: safeAreaLayoutGuide.bottomAnchor, right: sendButton.leftAnchor, paddingTop: 12, paddingLeft: 4, paddingBottom: -4 ,paddingRight: 8) addSubview(placeHolderLabel) placeHolderLabel.anchor(left: messageInputTextView.leftAnchor, paddingLeft: 4) placeHolderLabel.centerY(inView: messageInputTextView) NotificationCenter.default.addObserver(self, selector: #selector(handleTextInputChange), name: UITextView.textDidChangeNotification, object: nil) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override var intrinsicContentSize: CGSize { return .zero } //MARK: - Selector's @objc func handleSendMessage() { guard let text = messageInputTextView.text else {return} delegate?.inputView(self, wantsToSend: text) } @objc func handleTextInputChange() { placeHolderLabel.isHidden = !self.messageInputTextView.text.isEmpty sendButton.isEnabled = !self.messageInputTextView.text.isEmpty } //MARK: - Helpers func cleraMessageText() { messageInputTextView.text = nil placeHolderLabel.isHidden = false sendButton.isEnabled = false } }

xcode 11
swift 5

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

akaakoz

2020/06/23 23:43

uploadMessage関数の COLLECTION_MESSAGESってどこを参照してますか?
atk_721

2020/06/24 03:49

すいません。記載するのを忘れていました。public let COLLECTION_MESSAGES = Firestore.firestore.collection("messages") として定義しています!
atk_721

2020/06/24 13:48

user.uidがnilではなく""空文字になっていました。userインスタンスを作って保存する際に.uidを入れ忘れていました。回答ありがとうございました。
guest

回答1

0

自己解決

user.uidが空文字だった為、collectionIDが認識されませんでした。

投稿2020/06/24 13:50

atk_721

総合スコア62

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問