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

SwiftUI中如何独立识别并处理每条评论的回复操作?

解决SwiftUI评论区独立回复单条评论的问题

问题核心

当前使用全局布尔值isReply控制回复状态,导致所有评论的回复状态联动:点击新评论的回复按钮时,全局状态切换会关闭所有评论的回复状态,无法独立控制单条评论的回复操作。

解决方案

将全局布尔状态替换为可选评论ID,通过存储当前目标回复的评论ID来精准控制回复状态,支持无缝切换回复对象和取消回复。

1. 修改ViewModel状态管理

替换原有isReply和commentId为可选类型的targetReplyCommentId,用是否存在值来判断回复状态,同时关联回复目标ID:

class PostCommentsViewModel: ObservableObject {
    // 替换原有的isReply、commentId
    @Published var targetReplyCommentId: String?
    @Published var mention: String = ""
    @Published var commentText: String = ""
    @Published var isLoading: Bool = false
    // 其他原有属性...
    
    func addComment(onComplete: (()->())? = nil) {
        isLoading = true
        
        var parameters: [String: Any] = [
            // 主评论基础参数
        ]
        
        // 判断是否为回复操作
        if let replyTargetId = targetReplyCommentId {
            // 添加回复专属参数(如父评论ID)
            parameters["parentId"] = replyTargetId
        }
   
        functionForSendingData()
        
        // 提交后重置回复状态
        targetReplyCommentId = nil
        commentText = ""
        isLoading = false
        onComplete?()
    }
    
    // 优化:加载回复时直接接收评论ID参数,避免全局变量污染
    func getReplies(for commentId: String) {
        // 原有加载逻辑,使用传入的commentId而非全局变量
    }
    
    // 其他原有方法...
}

2. 更新MainCommentView回复按钮逻辑

修改回复按钮的点击事件,实现"切换回复/取消回复"的独立控制:

struct MainCommentView: View {
    var data: Comment
    @ObservedObject var viewModelObserved: PostCommentsViewModel
    @State private var showReplies: Bool = false
    @FocusState var isTextFieldFocused: Bool
    
    var body: some View {
        VStack(alignment:.leading) {
            HStack(alignment:.top) {
                // 用户头像、评论内容视图(保留原有代码)
                
                // 回复按钮
                Button {
                    let currentCommentId = data.id ?? "unknown"
                    
                    // 判断当前是否正在回复这条评论
                    if viewModelObserved.targetReplyCommentId == currentCommentId {
                        // 取消回复:清空状态和输入框
                        viewModelObserved.targetReplyCommentId = nil
                        viewModelObserved.commentText = ""
                        isTextFieldFocused = false
                    } else {
                        // 切换到回复这条评论:设置目标ID、填充@提及文本并聚焦输入框
                        viewModelObserved.targetReplyCommentId = currentCommentId
                        viewModelObserved.mention = "@\(data.user?.firstName ?? "unknown")"
                        viewModelObserved.commentText = "\(viewModelObserved.mention) "
                        isTextFieldFocused = true
                    }
                } label: {
                    // 可选:根据回复状态动态修改按钮文本和样式
                    let isReplyingToThis = viewModelObserved.targetReplyCommentId == data.id ?? "unknown"
                    Text(isReplyingToThis ? "Cancel Reply" : "Reply")
                        .font(.ubuntu(name: .ubuntuRegular, size: 12))
                        .foregroundStyle(isReplyingToThis ? Color.blue : Color.gray)
                }
                
                // 时间戳视图(保留原有代码)
                Text("\(viewModelObserved.formattedTime(dateString: data.createdAt ?? ""))")
                    .font(.ubuntu(name: .ubuntuRegular, size: 11))
                    .foregroundStyle(Color.gray)
                
            }
            
            // 显示/隐藏回复按钮(优化:直接传入评论ID加载回复)
            Button(showReplies ? "— Hide Replies (\(data.countReplies ?? 0))" : "— Show Replies(\(data.countReplies ?? 0))") {
                viewModelObserved.getReplies(for: data.id ?? "unknown")
                showReplies.toggle()
            }
            .font(.ubuntu(name: .ubuntuRegular, size: 14))
            .foregroundStyle(Color.gray.opacity(0.5))
            
            // 回复列表视图(保留原有代码)
            if showReplies {
                if let repliesData = viewModelObserved.repliesModel?.data?.comments {
                    ForEach(repliesData, id:\.id) { reply in
                        RepliesView(data: reply)
                    }
                }
            }
        }
        .padding(.horizontal, 10)
    }
}

3. 可选优化:高亮当前回复目标

为正在回复的评论添加视觉高亮,提升用户体验:

// 在MainCommentView的外层容器添加高亮样式
VStack(alignment:.leading) {
    // 原有内容
}
.padding(.horizontal, 10)
.background(
    viewModelObserved.targetReplyCommentId == data.id ?? "unknown" 
    ? Color.blue.opacity(0.05) 
    : Color.clear
)
.cornerRadius(8)

效果说明

  • 点击任意评论的"Reply"按钮,会进入针对该评论的回复状态,自动填充@提及文本并聚焦输入框
  • 再次点击该评论的"Cancel Reply"按钮,会取消回复状态,清空输入框
  • 点击其他评论的"Reply"按钮,会自动切换回复目标,无需手动取消之前的回复状态
  • 提交评论后,自动重置回复状态,回到正常评论模式

内容的提问来源于stack exchange,提问作者avisrapāx

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 21:00:35