我正在向一个项目添加评论,一切似乎都正常,但是我显示评论的表格 View 没有得到正确更新,直到我离开屏幕然后再次返回。
基本上,一旦输入评论并按下“发送”,评论连同评论作者就会被发布到 Firebase。然后循环包含这两个值的字典,评论进入一个数组,而评论作者进入另一个数组(这样我就可以用数组的索引路径填充我的 TableView ):
@IBAction func addCommentButtonPressed(_ sender: Any) {
if addCommentTextField.text != nil {
if let comment = addCommentTextField.text {
print(comment)
let ref = FIRDatabase.database().reference()
let keyToPost = ref.child("posts").childByAutoId().key
ref.child("posts").child(self.postID).observeSingleEvent(of: .value, with: { (snapshot) in
if let post = snapshot.value as? [String : AnyObject] {
let updateComments: [String: Any] = ["comments/\(FIRAuth.auth()!.currentUser!.displayName!)" : comment]
ref.child("posts").child(self.postID).updateChildValues(updateComments, withCompletionBlock: { (error, reff) in
if error == nil {
ref.child("posts").child(self.postID).observeSingleEvent(of: .value, with: { (snap) in
if let properties = snap.value as? [String: AnyObject] {
if let commentLoop = post["comments"] as? [String : AnyObject] {
for (person, comment) in commentLoop {
self.selectedPost.commentAuthors.append(person)
self.selectedPost.commentText.append(comment as! String)
}
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
})
}
})
}
})
ref.removeAllObservers()
}
}
addCommentTextField.resignFirstResponder()
self.addCommentTextField.text = nil
self.view.endEditing(true)
self.addCommentView.isHidden = true
}
这就是我的 Firebase 数据库的样子:
我不确定是什么问题。我觉得我在正确的地方调用了 self.tableView.reloadData()。这是我的获取函数(在显示图像的 FeedViewController 中,而不是具有注释的 PhotoDetailController - PhotoDetailController 是通过点击到达的在 FeedViewController 中的其中一张图片上):
func fetchPosts() {
let ref = FIRDatabase.database().reference()
ref.child("users").queryOrderedByKey().observe(.value, with: { snapshot in
let users = snapshot.value as! [String : AnyObject]
for (_, value) in users {
// get uid as string
if let uid = value["uid"] as? String {
// check to make sure uids match
if uid == FIRAuth.auth()?.currentUser?.uid {
// check for followers
if let followingUsers = value["following"] as? [String : String] {
// loop through those and add them to "following" array
for (_, user) in followingUsers {
self.following.append(user)
}
}
// add current user to that array also so you can see your own posts
self.following.append(FIRAuth.auth()!.currentUser!.uid)
ref.child("posts").queryOrderedByKey().observeSingleEvent(of: .value, with: { (snap) in
let postsSnap = snap.value as! [String : AnyObject]
for (_, post) in postsSnap {
if let userID = post["userID"] as? String {
for each in self.following {
if each == userID {
// here are the posts that the user should see (his own and his following)
let posst = Post()
if let author = post["author"] as? String, let likes = post["likes"] as? Int, let pathToImage = post["pathToImage"] as? String, let postID = post["postID"] as? String {
posst.author = author
posst.likes = likes
posst.pathToImage = pathToImage
posst.postID = postID
posst.userID = userID
if let people = post["peopleWhoLike"] as? [String : AnyObject] {
for (_, person) in people {
posst.peopleWhoLike.append(person as! String)
}
}
if let commentLoop = post["comments"] as? [String : AnyObject] {
for (person, comment) in commentLoop {
posst.commentAuthors.append(person)
posst.commentText.append(comment as! String)
}
}
posts.append(posst)
}
}
}
self.collectionView.reloadData()
}
}
})
ref.removeAllObservers()
}
}
}
})
}
问题是在发表评论后重新加载 tableView,还是在 fetch 函数中?就像我说的,一切似乎都与 firebase 一起正常工作,我只是希望包含要更新的评论的 tableView 在评论发布后立即显示。
编辑:感谢 Jen 的绝妙建议。我尝试了您的建议并做了一些小改动以消除警告/错误:
@IBAction func addCommentButtonPressed(_ sender: Any) {
if !addCommentTextField.text!.isEmpty {
addComment(comment: addCommentTextField.text!)
observePostComments()
}
}
func addComment(comment: String) {
let postsCommentsRef = FIRDatabase.database().reference().child("postComments").child(self.postID)
var commentData: [String: String] = [:]
commentData["userId"] = FIRAuth.auth()!.currentUser!.displayName!
commentData["comment"] = comment
postsCommentsRef.childByAutoId().setValue(commentData)
}
func observePostComments() {
let postsCommentsRef = FIRDatabase.database().reference().child("postComments").child(self.postID)
postsCommentsRef.observe(.childAdded, with: { snapshot in
let comment = snapshot.value as! [String: String]
self.selectedPost.commentAuthors.append(comment["userId"]!)
self.selectedPost.commentText.append(comment["comment"]!)
self.tableView.reloadData()
})
}
这些是我的 tableView 方法:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CommentCell
cell.commentAuthorLabel?.text = selectedPost.commentAuthors[indexPath.row]
cell.commentLabel?.text = selectedPost.commentText[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return selectedPost.commentAuthors.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 72
}
最佳答案
看起来 fetchPosts 既更新数据库又监听变化。我建议您设置一个仅更新数据库的功能。然后有一个单独的函数,该函数在 View 中调用一次,并使用 .observe(.childAdded) 将新评论附加到 tableView,只要它们出现在数据库中。
编辑: 由于您是 Firebase 的新手,这里有一些简化代码和更新 tableView 的具体建议:
在“帖子”之外创建一个单独的子项来保存评论。有时您可能想要从不包含评论的帖子中访问某些信息,因此最好通过保持数据库平坦来最大程度地减少下载的额外数据量。使用相同的 postId 链接帖子和帖子评论。
结果看起来像这样:
"posts":
"-postIdKey":
"photoPath": "..."
"name": "..."
"date": "..."
"...": "..."
"postComments:"
"-postIdKey":
"-commentIdPush1":
"userId": "uId1"
"comment": "Love this pic!"
"-commentIdPush2":
"userId": "uId2"
"comment": "Wow!"
在 addCommentButtonPressed 中,如果文本字段中有文本,则调用 addComment,将文本作为参数传递。创建一个字典来保存您将传递给 setValue 的数据。设置键“userId”和“comment”的值后,使用 childByAutoId 为 postCommentsRef 创建一个新的子项并传递评论数据。
@IBAction func addCommentButtonPressed(_ sender: Any) {
if !addCommentTextField.text!.isEmpty {
addComment(addCommentTextField.text!)
}
}
func addComment(comment: String) {
var commentData: [String: String] = [:]
commentData["userId"] = self.userID
commentData["comment"] = comment
postCommentsRef.childByAutoId().setValue(commentData)
}
与其观察 .value 的单个事件,不如通过创建一个观察新评论的监听器来利用 Firebase 数据库是实时的这一事实。您可以创建另一个仿照此函数的函数来收听新帖子。
let postsCommentsRef = FIRDatabase.database().reference().child("postComments").child(postID)
func observePostComments() {
postsCommentsRef.observe(.childAdded, with: { snapshot in
let comment = snapshot.value as! [String: String]
self.comments.append(comment["userId"])
self.commentAuthors.append(comment["comment"])
self.yourTableView.insertRows(at: [IndexPath(row: self.comments.count-1, section: 0)], with: .automatic)
})
}
请注意 #2 和 #3 中关注点的分离。 addCommentButtonPressed 只关心向数据库添加新评论。 observePostComments 只关心从数据库向 UITableView 添加新评论。
关于ios - Tableview 仅在我离开 View 并返回后更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42864160/
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
Arel3.0.2提供了两个类来指定连接类型:Arel::Nodes::InnerJoin和Arel::Nodes::OuterJoin并使用InnerJoin默认。foo=Arel::Table.new('foo')bar=Arel::Table.new('bar')foo.join(bar,Arel::Nodes::InnerJoin)#innerfoo.join(bar,Arel::Nodes::OuterJoin)#outerfoo.join(bar,???)#left如果要生成左连接,如何连接两个表? 最佳答案 你可以使用
我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案
我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下