Вызов комментариев для заполнения TableView: исправление ошибок кода - PullRequest
0 голосов
/ 21 июня 2019

Я пытаюсь заполнить мою таблицу комментариев комментариями из моих сообщений.У меня есть следующая структура базы данных JSON:

  {
  "posts" : {
    "-Lhu-XRs806sXSEQS2BF" : {
      "reports" : 0,
      "text" : "How can I improve my data structure?",
      "timestamp" : 1561120090116,
      "title" : "Hello Stack Exchange",
      "userID" : "nyRBXSyyDhc1Qkypou0Iz0iMsyr1"
    },
    "-Lhu-fI6DMSZvy8EdIgM" : {
      "reports" : 0,
      "text" : "As in Libre",
      "timestamp" : 1561120126347,
      "title" : "Free",
      "userID" : "nyRBXSyyDhc1Qkypou0Iz0iMsyr1"
    },
    "comments" : {
      "-Lhu-hXISy-0N2V4ES-a" : {
        "reports" : 0,
        "timestamp" : 1561120135594,
        "userID" : "nyRBXSyyDhc1Qkypou0Iz0iMsyr1"
      },
      "-Lhu-j1cR6V407tyUYY1" : {
        "reports" : 0,
        "timestamp" : 1561120141801,
        "userID" : "nyRBXSyyDhc1Qkypou0Iz0iMsyr1"
      },
      "-Lhu-lrJp9H8SQowlYWz" : {
        "reports" : 0,
        "timestamp" : 1561120153314,
        "userID" : "nyRBXSyyDhc1Qkypou0Iz0iMsyr1"
      },
      "posts" : {
        "-Lhu-XRs806sXSEQS2BF" : {
          "comments" : {
            "-Lhu-hXISy-0N2V4ES-_" : "How is it going?",
            "-Lhu-j1cR6V407tyUYY0" : "It’s good to see you"
          }
        },
        "-Lhu-fI6DMSZvy8EdIgM" : {
          "comments" : {
            "-Lhu-lrJp9H8SQowlYWy" : "Richard Stallman"
          }
        }
      }
    }
  }
}

И следующий класс комментариев:

class Comment {
    var id:String
    var text:String

    init(id: String, text:String) {
        self.id = id
        self.text = text
    }
}

Вот мой код после учета ваших предложений:

var comments = [Comment] ()
@IBOutlet weak var commentsTable: UITableView!
@IBOutlet weak var commentPlaceHolder: UILabel!
@IBOutlet weak var newCommentLabel: UITextView!
weak var delegate:NewPostVCDelegate?
let ref = Database.database().reference().child("posts")

@IBAction func reply(_ sender: UIButton) {
    let userID = (Auth.auth().currentUser?.uid)!
    addComment(toPostId: post!.id, andComment: newCommentLabel.text, commentByUid: userID)
    loadComments(forPostId: post!.id)
    comments.removeAll()
    commentsTable.reloadData()
    newCommentLabel.text = String()
    commentPlaceHolder.isHidden = false
}

func addComment(toPostId: String, andComment: String, commentByUid: String) {
    let commentsRef = self.ref.child("comments") //ref to the comments node
    let thisCommentRef = commentsRef.child(toPostId) //ref to a node with postId as key
    let commentToAddRef = thisCommentRef.childByAutoId() //each comment will have it's own key
    let d = [
        "comment_text": andComment,
        "comment_by_uid": commentByUid]
    commentToAddRef.setValue(d)
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    loadComments(forPostId: post!.id)
}

func loadComments(forPostId: String) {
    let ref = self.ref.child("comments")
    let thisPostRef = ref.child(forPostId)
    thisPostRef.observeSingleEvent(of: .value, with: { snapshot in

        let allComments = snapshot.children.allObjects as! [DataSnapshot]
        for commentSnap in allComments {
            let commenterUid = commentSnap.childSnapshot(forPath: "comment_by_uid").value as? String ?? "No uid"
            let commentText = commentSnap.childSnapshot(forPath: "comment_text").value as? String ?? "No comment"
            let aComment = Comment(id: commenterUid, text: commentText)
            self.comments.append(aComment)
            print(commenterUid, commentText)
        }
        self.commentsTable.reloadData()
    })
}

func adjustUITextViewHeight(arg : UITextView) {
    arg.translatesAutoresizingMaskIntoConstraints = true
    arg.sizeToFit()
    arg.isScrollEnabled = false
}

override func viewDidLoad() {
    super.viewDidLoad()
    self.commentsTable.dataSource = self
    let cellNib = UINib(nibName: "CommentTableViewCell", bundle: nil)
    commentsTable.register(cellNib, forCellReuseIdentifier: "postCell")
    view.addSubview(commentsTable)
    commentsTable.register(LoadingCell.self, forCellReuseIdentifier: "loadingCell")

    self.commentsTable.delegate = self
    mainText.isEditable = false
    titleText.isEditable = false
    commentsTable.register(cellNib, forCellReuseIdentifier: "postCell")
    view.addSubview(commentsTable)
    commentsTable.register(LoadingCell.self, forCellReuseIdentifier: "loadingCell")
    print(delegate!)
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return comments.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if indexPath.section == 0 {
        let cell = tableView.dequeueReusableCell(withIdentifier: "postCell", for: indexPath) as! CommentTableViewCell
        cell.set(comment: comments[indexPath.row])
        return cell
    } else {
        let cell = tableView.dequeueReusableCell(withIdentifier: "loadingCell", for: indexPath) as! LoadingCell
        cell.spinner.startAnimating()
        return cell
    }
}

func textViewDidChange(_ commentView: UITextView) {
    commentPlaceHolder.isHidden = !newCommentLabel.text.isEmpty
}

Включая комментарии Джея, я получил представление.Мне пришлось добавить comments.removAll (), чтобы он не распечатывал комментарии несколько раз в таблице comments.Однако func textViewDidChange больше не работает.Я не уверен, как решить эту проблему.Я попытался вызвать функцию без удачи.Может быть, изменение делегата повлияло на это?

Ответы [ 2 ]

1 голос
/ 22 июня 2019

Этот ответ основан на данных в вопросе и последующих комментариях.

Денормализация данных является стандартной практикой в ​​базах данных NoSQL, но в этом случае рассматриваемая структура может быть более сложной, чем необходимо.

Вот вопрос

Учитывая серию постов, где у каждого поста есть комментарии, как вы загружаете комментарии к каждому сообщению для отображения в табличном представлении.

Я собираюсь работать в обратном направлении от предложенной структуры

posts
   post_0 //created with .childByAutoId
      creator_uid: "the uid of whoever created this post"
      post_title: "My post about posting"

comments
   post_0 //ties back to the key of the post in the posts node
      comment_0 //created with .childByAutoId
         comment_by_uid: "whoever created this comment"
         comment_text: "comment about this post"
      comment_1
         comment_by_uid: "whoever created this comment"
         comment_text: "comment about this post"

Эта структура отделяет комментарии от поста, на который они ссылаются. В узле комментариев ключом к каждому узлу является post_id от узла posts. Это позволяет загружать сообщения в tableView без больших накладных расходов, и, например, если вы отображаете комментарии в detailView, загружайте все комментарии для определенного сообщения.

Обратите внимание, что узлы сообщений и ключи узлов комментариев создаются с помощью .childByAutoId ()

Теперь рабочий процесс. Предположим, что пользователь создает новый пост и ввел заголовок для поста и другой информации. Позвоните, чтобы создать сообщение в Firebase.

func createPost(withTitle: String, andCreatorUid: String) {
    let postsRef = self.ref.child("posts")
    let thisPost = postsRef.childByAutoId()
    let d = [
        "post_title": withTitle,
        "creator_uid": andCreatorUid
        ]
    thisPost.setValue(d)
}

Вот хитрый момент - то, что я делаю , имеет наблюдателя от узла сообщений. Когда добавляется новая запись, я получаю это событие, создаю объект PostsClass, который содержит информацию о записи, добавляет ее в мой массив dataSource, а затем обновляю tableView. Делая это, я также получаю ключ к узлу (который был создан с помощью .childByAutoId).

Другой пользователь видит это сообщение и хочет прокомментировать его, чтобы нажать на сообщение, чтобы ввести комментарий. Следующий код хранит их комментарий в Firebase.

func addComment(toPostId: String, andComment: String, commentByUid: String) {
    let commentsRef = self.ref.child("comments") //ref to the comments node
    let thisCommentRef = commentsRef.child(toPostId) //ref to a node with postId as key
    let commentToAddRef = thisCommentRef.childByAutoId() //each comment will have it's own key
    let d = [
        "comment_text": andComment,
        "comment_by_uid": commentByUid]
    commentToAddRef.setValue(d)
}

toPostId - это ключ к сообщению, полученный из объекта PostClass, который они выбрали для добавления комментария.

Наконец, чтобы специально ответить на вопрос, здесь идет загрузка комментариев к конкретному сообщению.

func loadComments(forPostId: String) {
    let ref = self.ref.child("comments")
    let thisPostRef = ref.child(forPostId)
    thisPostRef.observeSingleEvent(of: .value, with: { snapshot in

        let allComments = snapshot.children.allObjects as! [DataSnapshot]
        for commentSnap in allComments {
            let commenterUid = commentSnap.childSnapshot(forPath: "comment_by_uid").value as? String ?? "No uid"
            let commentText = commentSnap.childSnapshot(forPath: "comment_text").value as? String ?? "No comment"
            //create a commentClass object, update properties and add to dataSourceArray
            print(commenterUid, commentText)
        }
        //tableView reload
    })
}

Примечания:

У меня есть класс var, ref , поэтому self.ref указывает на мой корневой узел firebase. Вам нужно будет установить это, чтобы указать на ваш

Я использую post_0 и comment_0 в качестве имен ключей узла в этом ответе, так как его легче читать и понимать, чем ключ, такой как -LhzJD3tPL0xcnUDMaOZ , который фактически создает .childByAutoId в вашей базе данных.

0 голосов
/ 21 июня 2019

В этой строке Comment(id: childDataSnapshot.key, text: comments) вы передаете комментарии (это свойство массива), но вам нужно передать текст. Для перезагрузки данных используйте commentsTable.reloadData(). Для ошибки в cellForRowAt дважды проверьте, что вам нужно передать для настройки вашей ячейки, и проверьте, какой тип вы передаете в set(comment

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...