You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firebase点赞功能实现异常:点击点赞按钮后出现Optional值为nil问题

解决Firebase点赞功能中的Optional nil问题

我帮你梳理下代码里可能触发nil崩溃的点,以及优化点赞逻辑的方法:

1. 强制解包currentUser是高危操作

你代码里用了Auth.auth().currentUser!.uid,如果用户未登录,currentUser就是nil,强制解包会直接崩溃。先做安全检查:

guard let currentUserUID = Auth.auth().currentUser?.uid else {
    print("用户还没登录哦")
    self.like.isEnabled = true
    return
}

2. postID为空也会导致问题

如果首页的postID没正确赋值,self.postID就是nil,传给Firebase的child节点会出错。同样加个安全校验:

guard let postID = self.postID else {
    print("postID是空的,检查下首页的赋值逻辑")
    self.like.isEnabled = true
    return
}

3. 优化点赞数据存储的逻辑

你原本用childByAutoId()生成的key来存点赞用户UID,其实更合理的是用点赞用户的UID作为key——这样既能避免同一个用户重复点赞,还能让数据结构更直观。修改后的完整点击事件代码如下:

@IBAction func likePressed(_ sender: Any) {
    self.like.isEnabled = false
    
    // 安全获取当前用户UID
    guard let currentUserUID = Auth.auth().currentUser?.uid else {
        print("用户未登录,无法点赞")
        self.like.isEnabled = true
        return
    }
    
    // 安全获取被点赞用户的postID
    guard let postID = self.postID else {
        print("postID为空,请检查首页赋值")
        self.like.isEnabled = true
        return
    }
    
    let ref = Database.database().reference()
    
    // 先检查用户是否已经点过赞
    ref.child("people").child(postID).child("peopleWhoLike").child(currentUserUID).observeSingleEvent(of: .value) { snapshot in
        if snapshot.exists() {
            // 已经点过赞,可以加取消点赞的逻辑(可选)
            print("你已经点过赞啦")
            self.like.isEnabled = true
        } else {
            // 存入点赞记录:用当前用户UID作为key,值设为true即可
            let updateLikes: [String: Any] = ["peopleWhoLike/\(currentUserUID)" : true]
            ref.child("people").child(postID).updateChildValues(updateLikes) { error, _ in
                if let error = error {
                    print("点赞失败:\(error.localizedDescription)")
                    self.like.isEnabled = true
                    return
                }
                
                // 更新点赞数并同步到UI
                ref.child("people").child(postID).child("peopleWhoLike").observeSingleEvent(of: .value) { snap in
                    let likeCount = snap.childrenCount
                    self.likeLabel.text = "\(likeCount) Likes"
                    ref.child("people").child(postID).updateChildValues(["likes": likeCount])
                    self.like.isEnabled = true
                }
            }
        }
    }
    
    ref.removeAllObservers()
}

4. 修正首页postID的赋值代码

你首页的代码override func Table View: cell.postID = self.people[indexPath.row].postID语法不对,应该在cellForRowAt方法里正确赋值:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "你的CellID", for: indexPath) as! 你的自定义Cell类
    let targetPerson = self.people[indexPath.row]
    cell.postID = targetPerson.postID // 确保targetPerson有postID属性且不为空
    // 其他UI赋值逻辑...
    return cell
}

修改后,你的Firebase数据库会变成预期的结构:

"people" : {
    "9RYUttVhCzXKs6H1XnZ63TZ8Dun2" : {
        "Coordinates" : {
            "latitude" : 15.78583,
            "longitude" : -4.406417
        },
        "Education" : "CS",
        "PhotoPosts" : "https://firebasestorage.googleapis.com/v0/b/daylike-2f938.appspot.com/o/images%2FPhotoPosts?alt=media&token=ac9e574f-b55f-4bf0-b75b-79b877a86480",
        "caption" : 1563439869418,
        "users" : "nane19@aol.com",
        "peopleWhoLike": {
            "点赞用户的UID": true
        },
        "likes": 1
    }
}

这样既解决了Optional nil的崩溃问题,又优化了点赞逻辑,避免重复点赞,数据结构也更清晰。

内容的提问来源于stack exchange,提问作者noname87f

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:22:07