Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 展开时发现无可选_Ios_Swift_Uitableview_Firebase Realtime Database - Fatal编程技术网

Ios 展开时发现无可选

Ios 展开时发现无可选,ios,swift,uitableview,firebase-realtime-database,Ios,Swift,Uitableview,Firebase Realtime Database,我试图创建一个聊天应用程序,但我遇到的问题是,我试图让tableview中的单元格显示用户的displayname。但出于某种原因,它一直在说零。这让我相信我的结构或引用数据的方式有问题 Struct struct User { let name: String! let uid: String! } 表格视图单元格 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPa

我试图创建一个聊天应用程序,但我遇到的问题是,我试图让tableview中的单元格显示用户的displayname。但出于某种原因,它一直在说零。这让我相信我的结构或引用数据的方式有问题

Struct

struct User {
    let name: String!
    let uid: String!
}
表格视图单元格

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)

    // **** Crash is on the following line ****
    let nameTxtField = cell.viewWithTag(1) as! UILabel
    nameTxtField.text = users[indexPath.row].name
    return cell
}
表格视图viewDidload

override func viewDidLoad() {
    super.viewDidLoad()
    let uid = Auth.auth().currentUser?.uid

    let ref: DatabaseReference! = Database.database().reference()

    ref.child("users").child(uid!).queryOrderedByKey().observe(.childAdded) { (snapshot) in
        let name = (snapshot.value as? NSDictionary)?["name"] as? String ?? ""

        let uid = (snapshot.value as? NSDictionary)?["uid"] as? String ?? ""

        self.users.append(User(name: name, uid: uid))

        self.tableView.reloadData()
    }

    tableView.reloadData()
}
数据库结构

仅当您希望根据某些条件从列表中获取多个子项时,才需要使用由…和
排序的
查询。但在本例中,您知道子节点的确切路径,因此不需要查询

因此,您正在执行直接读取,但使用的是
queryOrderedByKey()
.childAdded
。这意味着您的闭包将在
/users/rPJSO…
下与每个子项一起调用,每个属性调用一次:
email
name
password
uid
。由于在这些属性下都没有
name
property,因此对它们的查找将返回
nil

解决方案非常简单:删除
queryOrderedByKey
并侦听
.value

ref.child("users").child(uid!).observe(.value) { (snapshot) in
  ...

您的其余代码可以保持不变。

仅当您希望根据某些条件从列表中获取多个子项时,才需要使用由…
定义的
查询。但在本例中,您知道子节点的确切路径,因此不需要查询

因此,您正在执行直接读取,但使用的是
queryOrderedByKey()
.childAdded
。这意味着您的闭包将在
/users/rPJSO…
下与每个子项一起调用,每个属性调用一次:
email
name
password
uid
。由于在这些属性下都没有
name
property,因此对它们的查找将返回
nil

解决方案非常简单:删除
queryOrderedByKey
并侦听
.value

ref.child("users").child(uid!).observe(.value) { (snapshot) in
  ...

您的代码的其余部分可以保持不变。

根据您的评论,您的代码正在崩溃

let nameTxtField = cell.viewWithTag(1) as! UILabel
这意味着
viewWithTag(1)
要么返回
nil
,要么返回
UILabel
以外的内容。您没有将标签的标记设置为1,或者您有多个带有标记1的UI元素(
viewWithTag
将返回带有该标记的层次结构中的第一个视图)

您应该创建一个适当的
UITableViewCell
子类,并将
UILabel
链接到该类上的属性。然后你可以这样说:

let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! MyTableViewCell
cell.nameTxtField.text = users[indexPath.row].name
其他一些评论;你应该试着消除尽可能多的!尽可能的

  • 结构的属性应该是可选的或非可选的,而不是隐式展开的可选
  • 您应该使用
    guard
    语句检索
    uid
    ,而不是稍后强制展开它
  • 如果您将获取用户的代码分散在几行上,它将更清晰
  • 避免在Swift中使用
    NS…
    对象
  • 我还注意到Frank关于您访问Firebase的方式的回答,但我对Firebase了解不够,不知道这是否是一个问题


根据你的评论,你在电话线上遇到了车祸

let nameTxtField = cell.viewWithTag(1) as! UILabel
这意味着
viewWithTag(1)
要么返回
nil
,要么返回
UILabel
以外的内容。您没有将标签的标记设置为1,或者您有多个带有标记1的UI元素(
viewWithTag
将返回带有该标记的层次结构中的第一个视图)

您应该创建一个适当的
UITableViewCell
子类,并将
UILabel
链接到该类上的属性。然后你可以这样说:

let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! MyTableViewCell
cell.nameTxtField.text = users[indexPath.row].name
其他一些评论;你应该试着消除尽可能多的!尽可能的

  • 结构的属性应该是可选的或非可选的,而不是隐式展开的可选
  • 您应该使用
    guard
    语句检索
    uid
    ,而不是稍后强制展开它
  • 如果您将获取用户的代码分散在几行上,它将更清晰
  • 避免在Swift中使用
    NS…
    对象
  • 我还注意到Frank关于您访问Firebase的方式的回答,但我对Firebase了解不够,不知道这是否是一个问题


问题似乎就在这一行:

let nameTxtField = cell.viewWithTag(1) as! UILabel
尚未从情节提要加载单元格,因此
cell.viewWithTag(1)
为零。零+!=撞车

通常我用以下算法填充单元格:

  • 为每种类型的单元格创建单独的类
  • 实现方法
    customizeUI()
    ,以填充单元格上必要的UI控件
  • 添加要在此单元格中显示的数据类型的iVar,并在其setter中调用customizeUI()

    变量项:历史项目?{ 迪塞特{ () } }

  • 此方法检查单元格是否已加载:

    func customizeUI() {
        guard let label = self.nameLabel else {
            return
        }
        // Fill UI controlls
        label.text = item.name
        ...
    }
    
    此外,必须在单元格
    awakeFromNib()
    方法中调用此方法


    最后,在您的
    cellAt…
    方法中,您必须编写类似于
    cell.item=dataItem
    的内容,而不是直接填充UI控件。

    问题似乎出在这一行:

    let nameTxtField = cell.viewWithTag(1) as! UILabel
    
    尚未从情节提要加载单元格,因此
    cell.viewWithTag(1)
    为零。零+!=撞车

    通常我用以下算法填充单元格:

  • 为每种类型的单元格创建单独的类
  • 实现方法
    customizeUI()
    ,以填充单元格上必要的UI控件