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

Swift中如何通过回调闭包在ViewController与Checker之间传递数据并实现校验UI反馈

用闭包实现文本校验后的UI更新方案

嗨!作为Swift新手,能尝试用闭包替代通知真的很棒——闭包其实就是一种能在任务完成后直接传递结果的回调工具,比通知更贴合这种一对一的场景,逻辑也更清晰。我来一步步帮你改造代码:

第一步:改造CheckTextField类,添加闭包回调

首先咱们给校验类加个回调能力,让它能把校验结果“告诉”ViewController。先定义一个枚举来明确三种状态(空、正确、错误),然后给check方法添加闭包参数:

// 先定义校验结果的枚举,让状态更清晰
enum CheckResult {
    case empty
    case correct
    case incorrect
}

class CheckTextField {
    private let correctWord = "correct word"
    
    // 修改check方法,接受一个闭包参数,用来传递校验结果
    func check(word: String, completion: (CheckResult) -> Void) {
        guard !word.isEmpty else {
            // 文本为空,返回empty状态
            completion(.empty)
            return
        }
        
        if word == correctWord {
            completion(.correct)
        } else {
            completion(.incorrect)
        }
    }
}

这里的completion就是闭包参数,它的类型是(CheckResult) -> Void——意思是“接受一个CheckResult类型的参数,没有返回值”。当校验完成时,我们调用这个闭包把结果传出去。

第二步:修改ViewController,用闭包处理校验结果

接下来咱们更新ViewController里的按钮点击逻辑,调用checker的校验方法,并通过闭包回调更新label的UI:

final class FeedViewController: UIViewController {
    private let checkTextField: UITextField = {
        let textField = MyCustomTextField(
            font: UIFont.systemFont(ofSize: 16),
            textColor: .black,
            backgroundColor: .white,
            placeholder: "Enter the word"
        )
        return textField
    }()
    
    private lazy var checkButton: UIButton = {
        let button = MyCustomButton(
            title: "Check the word",
            titleColor: .white,
            backgroundColor: .systemGray,
            backgroundImage: nil
        ) { [weak self] in
            // 按钮点击时,调用校验逻辑
            guard let self = self else { return }
            let inputWord = self.checkTextField.text ?? ""
            // 调用checker的check方法,传入闭包处理结果
            self.checker.check(word: inputWord) { result in
                // 回到主线程更新UI(因为闭包可能在后台执行,UI操作必须在主线程)
                DispatchQueue.main.async {
                    switch result {
                    case .empty:
                        self.colorLabel.alpha = 0
                    case .correct:
                        self.colorLabel.alpha = 1
                        self.colorLabel.textColor = .green
                    case .incorrect:
                        self.colorLabel.alpha = 1
                        self.colorLabel.textColor = .red
                    }
                }
            }
        }
        button.layer.cornerRadius = 6
        button.clipsToBounds = true
        return button
    }()
    
    private let colorLabel: UILabel = {
        let label = UILabel()
        label.alpha = 0
        label.toAutoLayout()
        return label
    }()
    
    private let checker: CheckTextField
    
    init(checker: CheckTextField) {
        self.checker = checker
        super.init(nibName: nil, bundle: nil)
    }
    
    // 别忘了添加required init(如果用代码创建VC的话)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

几个关键细节说明:

  • [weak self]:在按钮的闭包里用弱引用self,避免循环引用(按钮持有self,self持有按钮,闭包如果强引用self会导致内存泄漏)
  • DispatchQueue.main.async:确保UI更新操作在主线程执行——虽然当前校验是同步的,但如果以后校验改成异步(比如网络请求),这一步能保证UI操作安全
  • 闭包直接接收CheckResult,通过switch分支处理三种状态,逻辑一目了然

这样改造后,整个流程就变成了:按钮点击 → 调用checker校验 → 校验完成后通过闭包返回结果 → 更新label的颜色和透明度,比通知更直接,代码耦合度也更低。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 13:12:38