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

Swift:如何通过布尔变量更新关注/取消关注按钮标题

问题:无法根据关注状态更新Instagram式的关注/取消关注按钮

我想要实现一个类似Instagram的关注/取消关注按钮,目前的实现代码如下:

为按钮创建了IBOutlet并通过didSet设置属性:

@IBOutlet weak var followButtonOutlet: UIButton! {
    didSet {
        if !following {
            followButtonOutlet.setTitle("Follow", for: .normal)
            followButtonOutlet.backgroundColor = Colors.indexedPrimary
        } else {
            followButtonOutlet.setTitle("Unfollow", for: .normal)
            followButtonOutlet.backgroundColor = Colors.indexedPrimary
        }
    }
}

同时定义了following布尔变量,通过检查Firestore数据判断用户是否已关注:

func checkIfUserIsFollowing(){
    guard let currentUID = Auth.auth().currentUser?.uid, let userID = user.uid else { return }

    COLLECTION_USERS.document(currentUID).collection("following").document(userID).getDocument { snapshot, err in
        
        if let snapshot = snapshot {
            if snapshot.exists == true {
                self.following = true
            } else {
                self.following = false
            }
        } else {
            print("Error retrieving document: \(err)")
        }
    }
}

现在遇到的问题是:按钮无法根据用户是否在关注列表中更新标题和状态。未关注时应该显示“Follow”,已关注时显示“Unfollow”,请问正确的实现方式是什么?


解决方法

你的问题核心在于**following变量变化时没有触发按钮的更新逻辑**——当前的didSet只在followButtonOutlet被初始化或重新赋值时执行,而following改变时不会自动调用这段代码。按以下步骤修改:

  1. 给following变量添加didSet观察者,变量变化时直接更新按钮状态
var following: Bool = false {
    didSet {
        updateFollowButtonState()
    }
}
  1. 把按钮的UI更新逻辑抽成独立方法,方便复用和维护
private func updateFollowButtonState() {
    // 确保按钮已加载,避免nil报错
    guard let button = followButtonOutlet else { return }
    
    if following {
        button.setTitle("Unfollow", for: .normal)
        // 可选优化:已关注时切换为浅灰边框样式,和Instagram保持一致
        button.backgroundColor = .systemGray5
        button.setTitleColor(.label, for: .normal)
        button.layer.borderWidth = 1
        button.layer.borderColor = UIColor.systemGray4.cgColor
    } else {
        button.setTitle("Follow", for: .normal)
        button.backgroundColor = Colors.indexedPrimary
        button.setTitleColor(.white, for: .normal)
        button.layer.borderWidth = 0
    }
}
  1. 调整Outlet的didSet,只在按钮初始化时调用一次更新方法
@IBOutlet weak var followButtonOutlet: UIButton! {
    didSet {
        updateFollowButtonState()
    }
}
  1. 优化checkIfUserIsFollowing(),确保在主线程更新UI(Firestore回调默认在后台线程)
func checkIfUserIsFollowing(){
    guard let currentUID = Auth.auth().currentUser?.uid, let userID = user.uid else { return }

    COLLECTION_USERS.document(currentUID).collection("following").document(userID).getDocument { snapshot, err in
        DispatchQueue.main.async {
            if let snapshot = snapshot {
                self.following = snapshot.exists
            } else {
                print("Error retrieving document: \(err)")
            }
        }
    }
}
  1. 实现按钮点击的关注/取消关注逻辑,操作完成后更新following变量(自动触发UI刷新)
@IBAction func followButtonTapped(_ sender: UIButton) {
    guard let currentUID = Auth.auth().currentUser?.uid, let userID = user.uid else { return }
    
    if following {
        // 取消关注:同时删除当前用户following和目标用户followers集合中的记录
        COLLECTION_USERS.document(currentUID).collection("following").document(userID).delete { [weak self] err in
            if let err = err {
                print("取消关注失败:\(err)")
                return
            }
            COLLECTION_USERS.document(userID).collection("followers").document(currentUID).delete { err in
                if let err = err {
                    print("更新对方粉丝列表失败:\(err)")
                    return
                }
                DispatchQueue.main.async {
                    self?.following = false
                }
            }
        }
    } else {
        // 关注:同时添加到当前用户following和目标用户followers集合
        let timestamp = Timestamp(date: Date())
        let followingData = ["timestamp": timestamp]
        COLLECTION_USERS.document(currentUID).collection("following").document(userID).setData(followingData) { [weak self] err in
            if let err = err {
                print("关注失败:\(err)")
                return
            }
            let followerData = ["timestamp": timestamp]
            COLLECTION_USERS.document(userID).collection("followers").document(currentUID).setData(followerData) { err in
                if let err = err {
                    print("更新粉丝列表失败:\(err)")
                    return
                }
                DispatchQueue.main.async {
                    self?.following = true
                }
            }
        }
    }
}

关键说明

  • following的didSet是核心:每次变量变化都会自动触发按钮UI更新
  • 将UI逻辑抽成独立方法,避免重复代码,也方便后续调整样式
  • Firestore回调在后台线程,必须切换到主线程更新UI,否则可能导致界面无响应
  • 关注/取消关注时要同时维护两个集合(当前用户的following和目标用户的followers),保证数据一致性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 18:22:30