- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的问题几乎和这里一样:Firebase get child ID swift ios与这个问题略有不同 Retrieve randomly generated child ID from Firebase .
我有一个 UITableViewController,用户可以在其中创建自己的 channel 。每个人都可以查看这些 channel ,每个人都可以点击其中一个 channel ,然后进入一个新的 View 。现在,当用户点击这些单元格中的任何一个时,我想获取用户刚刚点击的当前 channel ID。
现在我的问题是:如何获得当前 ID (-KdD6[...]Q0Q)?问题 2 的答案对房间的创建者有用,但不能被其他用户使用,因为他们没有创建 key 。可以使用问题 1 的答案,但截至目前,它只是循环遍历每个随 secret 钥。但我需要与用户当前所在 channel 相关的 key 。下面是一些代码,用于展示我目前如何创建 channel 。提前致谢。编辑:这是我所有的代码。我现在在 didSelectRow 函数中收到错误“[Channel] 类型的值没有成员‘name’”。
import UIKit
import Firebase
import Foundation
enum Section: Int {
case createNewChannelSection = 0
case currentChannelsSection
}
extension multiplayerChannelView: UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
filterContentForSearchText(searchText: searchController.searchBar.text!)
}
}
class multiplayerChannelView: UITableViewController {
// MARK: Properties
var channels: [Channel] = []
let searchController = UISearchController(searchResultsController: nil)
var filteredChannels = [Channel]()
private lazy var channelRef: FIRDatabaseReference = FIRDatabase.database().reference().child("channels")
private var channelRefHandle: FIRDatabaseHandle?
var senderDisplayName: String?
var newChannelTextField: UITextField?
override func viewDidLoad() {
super.viewDidLoad()
title = "Rooms"
observeChannels()
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
tableView.tableHeaderView = searchController.searchBar
}
deinit {
if let refHandle = channelRefHandle {
channelRef.removeObserver(withHandle: refHandle)
}
}
func filterContentForSearchText(searchText: String, scope: String = "All") {
filteredChannels = channels.filter { Channel in
return (Channel.name.lowercased().range(of: searchText.lowercased()) != nil)
}
tableView.reloadData()
}
@IBAction func createChannel(_ sender: AnyObject) {
if let name = newChannelTextField?.text {
let newChannelRef = channelRef.childByAutoId()
let channelItem = [ // 3
"name": name
]
newChannelRef.setValue(channelItem)
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
private func observeChannels() {
channelRefHandle = channelRef.observe(.childAdded, with: { (snapshot) -> Void in // 1
let channelData = snapshot.value as! Dictionary<String, AnyObject> // 2
let id = snapshot.key
if let name = channelData["name"] as! String!, name.characters.count > 0 { // 3
self.channels.append(Channel(id: id, name: name))
self.tableView.reloadData()
} else {
print("Error! Could not decode channel data")
}
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let currentSection: Section = Section(rawValue: section) {
switch currentSection {
case .createNewChannelSection:
return 1
case .currentChannelsSection:
if searchController.isActive && searchController.searchBar.text != "" {
return filteredChannels.count
}
else{
return channels.count
}
}
} else {
return 0
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let reuseIdentifier = (indexPath as NSIndexPath).section == Section.createNewChannelSection.rawValue ? "NewChannel" : "ExistingChannel"
let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath)
if (indexPath as NSIndexPath).section == Section.createNewChannelSection.rawValue {
if let createNewChannelCell = cell as? CreateChannelCell {
newChannelTextField = createNewChannelCell.newChannelNameField
}
} else if (indexPath as NSIndexPath).section == Section.currentChannelsSection.rawValue {
if searchController.isActive && searchController.searchBar.text != "" {
cell.textLabel?.text = filteredChannels[(indexPath as NSIndexPath).row].name
} else {
cell.textLabel?.text = channels[(indexPath as NSIndexPath).row].name
}
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.section == Section.currentChannelsSection.rawValue {
var channel = channels
if searchController.isActive && searchController.searchBar.text != "" {
channel = [filteredChannels[(indexPath as NSIndexPath).row]]
channelRef.queryOrdered(byChild: "name").queryEqual(toValue: channel.name).observe(.childAdded, with: {snapshot in
let currentID = snapshot.key
print(currentID)
})
}
else
{
channel = [channels[(indexPath as NSIndexPath).row]]
channelRef.queryOrdered(byChild: "name").queryEqual(toValue: channel.name).observe(.childAdded, with: {snapshot in
let currentID = snapshot.key
print(currentID)
})
}
self.performSegue(withIdentifier: "ShowChannel", sender: channel)
}
}
}
internal class Channel {
internal let id: String
internal let name: String
init(id: String, name: String) {
self.id = id
self.name = name
}
}
编辑 2:我阅读了关于 prepare for segue 的内容,但是这不会正确执行:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
if let channel = sender as? Channel {
let chatVc = segue.destination as! channelMultiplayerViewController
chatVc.channel = channel
chatVc.channelRef = channelRef.child(channel.id)
}
}
执行 prepare for segue 函数,但是 if let channel = sender as? Channel 不是,因为它是 nil。
最佳答案
您必须向 firebase 查询 key 。当前设置的唯一问题是您希望防止重复名称。这样做的原因是,如果您没有在应用程序中存储每个 channel 的所有 key 并且必须查询 key ,则查询确切 key 的唯一方法是通过单独的节点“名称”。如果存在重复名称,那么我添加到您的 did select row 方法的代码中的 childAdded 将返回两个,并且没有其他数据可以帮助识别它。
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.section == Section.currentChannelsSection.rawValue {
var channel = channels
if searchController.isActive && searchController.searchBar.text != "" {
channel = [filteredChannels[(indexPath as NSIndexPath).row]]
channelRef.queryOrdered(byChild: "name").queryEqual(toValue: channel.name).observe(.childAdded, with: {snapshot in
let currentID = snapshot.key
})
}
else
{
channel = [channels[(indexPath as NSIndexPath).row]]
channelRef.queryOrdered(byChild: "name").queryEqual(toValue: channel.name).observe(.childAdded, with: {snapshot in
let currentID = snapshot.key
})
}
self.performSegue(withIdentifier: "ShowChannel", sender: channel)
}
}
我建议您获取已加载的所有 channel 的数据:
override func viewDidLoad(){
channelRef.observe(.childAdded, with: {snapshot in
let data = snapshot.value as? [String:Any] ?? [:]
let key = snapshot.key
let name = data["name"]
let chnl = Channel.init(id:key, name:name)
self.channels.append(chnl)
self.tableView.reloadData()
})
}
当您使用 .childAdded 时,此 VC 的监听器将处于事件状态,因此无论您何时创建新 channel ,都会调用此代码并重新加载您的表格。
否则您可以在创建 channel 时直接获取他们的 key :
@IBAction func createChannel(_ sender: AnyObject) {
if let name = newChannelTextField?.text {
let newChannelRef = channelRef.childByAutoId()
let channelItem = [
"name": name
]
newChannelRef.setValue(channelItem)
let channelKey = newChannelRef.key
let newChannel = Channel.init(id:channelKey, name:name)
self.channels.append(newChannel)
self.tableView.reloadData()
}
请注意,如果您走这条路线,则不会有任何新添加的项目的活跃监听器,这意味着如果另一台设备正在添加 channel ,那么其他设备将不会获得更新。最好通过查询从 firebase 中获取新创建的数据,并在将数据添加到数组时重新加载表。
这是一个适用于上述情况的示例 Channel 类:
import Foundation
// import FirebaseDatabase // import this if you would like to use this class to handle data transactions
class Channel: NSObject {
// change either of these to var if they should be mutable
let id:String
let name:String
// initialize
init (_ id:String, name:String){
self.id = id
self.name = name
}
}
这样您就有了一个可以使用的模型对象。如果您不熟悉 MVC 编码风格,您应该检查一下。它使应用程序更加高效。您可以采用此 Channel 模型并添加数据检索编码,以便此类为您的 Controller 处理数据。不过,这远远超出了您帖子的范围。现在这个类应该工作。
根据最后一条评论编辑:在 channel 选择期间在两个查询 block 中添加您的 prepareforsegue 方法,而不是在 if block 之后,因为它可能会在查询完成之前执行 prepare for segue。不过要注意一件事,在我意识到这一点之前,我曾经和你做过同样的事情;是您此时不必运行查询来获取所选单元格的数据,因为它在您的本地数组中。嗯,目前你只听添加的 child 。您还可以监听已删除和更改的子项,以便始终更新您的本地数据,然后当您选择单元格时,您可以直接访问 filteredChannels/channels 数组并通过 prepareforsegue 方法推送 channel 。我开始这样做是因为在表选择期间查询总是会导致奇怪的错误,我必须找到创造性的方法。
childRemoved 和 childChanged 查询可以像您当前的 .childAdded 方法一样实现,因为您希望保留监听器的处理程序以在页面取消时删除它们。但是,如果您不允许删除或更新 channel ,则可以忽略它。
关于swift - 使用 UITableViewController 从 Firebase 获取当前子 ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42308435/
出现在 python 2.7.8 中。 3.4.1 不会发生这种情况。 示例: >>> id(id) 140117478913736 >>> id(id) 140117478913736 >>> id
好吧,我对动态创建的控件的 ID 很困惑。 Public Class TestClass Inherits Panel Implements INamingContainer
我收到下面的错误,说有堆栈溢出。发生这种情况是因为带有 IN (id, id, id...id) 的 SQL 语句有大量参数。有没有什么办法解决这一问题?这是在我使用 Eclipse 的本地环境中发生
为什么 CPython(不知道其他 Python 实现)有以下行为? tuple1 = () tuple2 = ()
为什么 CPython(对其他 Python 实现一无所知)有以下行为? tuple1 = () tuple2 = ()
非常简单的问题:当我有一个持久对象时,它通常有一个名为 ID 的属性(对于抽象类)。 那么..命名约定是ID还是Id? 例如。 public int ID { get; set; } 或 public
知道为什么我会收到此错误,我已经尝试了所有命名约定(小写/大写) 我正在使用 Vaadin,这是我的代码片段: public class Usercontainer extends BeanI
为什么 CPython(不知道其他 Python 实现)有以下行为? tuple1 = () tuple2 = ()
我需要改变表的所有主键 UPDATE TODO SET id = id + 1 但我做不到(Demo 来自 Ahmad Al-Mutawa 的回答)描述了原因。主键不能这样改。 我也不能根据这是 sq
我正在尝试列出与用户相关的讨论列表。 想象一下,如果你愿意的话: posts -------------------------------------------------------------
我有一个表,其中包含一些具有自己的 ID 和共享 SKU key 的文章。我尝试使用左连接进行查询,并使用组结果获取从查询返回的所有 id。 我的数据结构是这样的: id - name -
在下表People中: id name 1 James 2 Yun 3 Ethan 如果我想找到最大 ID,我可以运行此查询 select max(id) id from People; 结果是
我正在产品页面上创建评论模块,其中显示垃圾评论选项,并显示 onclick 显示和隐藏弹出窗口。现在它在单个评论中工作正常但是当评论是两个时它同时打开两个因为类是相同的。现在这就是为什么我想要获取父
根据 REST 哲学,PUT操作应该(取自维基百科): PUT http://example.com/resources/142 Update the address member of the co
我想知道如何在使用 PHP 或 JavaScript 进行身份验证后从 Google Analytics 获取 Property Id、View Id 和 Account Id?因为我希望能够将它们存
我想使用所选按钮的 ID 进行删除。但我不知道如何从中获取/获取 id。我尝试了 this.id 但不起作用。 这是我创建按钮的地方: var deleteEmployer= document.cre
我有一个具有以下结构的表“表” ID LinkedWith 12 13 13 12 14 13 15 14 16
请不要在未阅读问题的情况下将问题标记为重复。我确实发布了一个类似的问题,但 STACKOVERFLOW 社区成员要求我单独重新发布修改后的问题,因为考虑到一个小而微妙的修改,解决方案要复杂得多。 假设
在 Android Studio 中,我创建了一个 Person.java 类。我使用Generate 创建了getter 和setter 以及构造函数。 这是我的 Person.java 类: pu
如何在 jQuery 中制作这样的东西: //这是显示的主体 ID //当我悬停 #hover-id 时,我希望 #principal-id 消失并更改 。但是当我将光标放在 #this-id 上时
我是一名优秀的程序员,十分优秀!