Swift 中的Combine使用场景

247 阅读1分钟

Swift 中的Combine 具体使用

本示例基于 Combine 框架实现手机号登录功能,包含手机号输入、验证码输入、协议同意、验证码倒计时、按钮状态绑定以及模拟网络请求。

主要功能点

  • 手机号输入:限制11位数字,实时校验有效性。
  • 验证码输入:限制4位数字,实时校验有效性。
  • 协议开关:用户必须同意协议才能登录。
  • 获取验证码按钮:手机号有效且倒计时结束时启用,点击后开始60秒倒计时。
  • 登录按钮:手机号有效、验证码有效且协议同意时启用。
  • 网络请求模拟:发送验证码和登录请求均模拟异步网络调用,随机成功或失败。

Combine 语法流程图

1123333.png

代码关键点

// 绑定手机号输入限制和发布
NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: phoneNumberField)
    .compactMap { ($0.object as? UITextField)?.text }
    .map { text -> String in
        if text.count > 11 {
            return String(text.prefix(11))
        }
        return text
    }
    .sink { [weak self] limitedText in
        if self?.phoneNumberField.text != limitedText {
            self?.phoneNumberField.text = limitedText
        }
        self?.phone = limitedText
    }
    .store(in: &subscriptions)
​
// 手机号有效性校验
var phoneValid: AnyPublisher<Bool, Never> {
    $phone
        .map { $0?.count == 11 }
        .eraseToAnyPublisher()
}
​
// 验证码有效性校验
var verifyCodeValid: AnyPublisher<Bool, Never> {
    $verifyCode
        .map { $0?.count == 4 }
        .eraseToAnyPublisher()
}
​
// 按钮状态绑定
Publishers.CombineLatest3(phoneValid, verifyCodeValid, $isAgree)
    .map { $0 && $1 && $2 }
    .receive(on: RunLoop.main)
    .assign(to: .isEnabled, on: logInBtn)
    .store(in: &subscriptions)
​
// 获取验证码按钮状态绑定(需倒计时为0)
phoneValid
    .combineLatest($verifyCodeCountdown)
    .map { $0 && $1 == 0 }
    .receive(on: RunLoop.main)
    .assign(to: .isEnabled, on: sendVerifyBtn)
    .store(in: &subscriptions)
​
// 模拟网络请求示例
func requestSendVerifyCode(phone: String) -> AnyPublisher<Bool, Error> {
    Future<Bool, Error> { promise in
        DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
            if Int.random(in: 1...100) <= 90 {
                promise(.success(true))
            } else {
                promise(.failure(NetworkError.failedToSendCode))
            }
        }
    }
    .receive(on: RunLoop.main)
    .eraseToAnyPublisher()
}

该示例清晰展示了如何用 Combine 处理表单输入校验、按钮状态绑定和异步网络请求,适合初学者理解和应用,详情请见demo