Swift - RxSwift的使用詳解22(UI控件擴展2:UITextField、UITextView)

二、UITextField 與 UITextView

1,監(jiān)聽單個 textField 內(nèi)容的變化(textView 同理)

(1)下面樣例中我們將 textField 里輸入的內(nèi)容實時地顯示到控制臺中。

(2)樣例代碼

注意.orEmpty 可以將 String? 類型的 ControlProperty 轉成 String,省得我們再去解包。

import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
     
    let disposeBag = DisposeBag()
     
    override func viewDidLoad() {
         
        //創(chuàng)建文本輸入框
        let textField = UITextField(frame: CGRect(x:10, y:80, width:200, height:30))
        textField.borderStyle = UITextBorderStyle.roundedRect
        self.view.addSubview(textField)
         
        //當文本框內(nèi)容改變時,將內(nèi)容輸出到控制臺上
        textField.rx.text.orEmpty.asObservable()
            .subscribe(onNext: {
                print("您輸入的是:\($0)")
            })
            .disposed(by: disposeBag)
    }
}

(3)當然我們直接使用 change 事件效果也是一樣的。

//當文本框內(nèi)容改變時,將內(nèi)容輸出到控制臺上
textField.rx.text.orEmpty.changed
    .subscribe(onNext: {
        print("您輸入的是:\($0)")
    })
    .disposed(by: disposeBag)

2,將內(nèi)容綁定到其他控件上

(1)效果圖

  • 我們將第一個 textField 里輸入的內(nèi)容實時地顯示到第二個 textField 中。
  • 同時 label 中還會實時顯示當前的字數(shù)。
  • 最下方的“提交”按鈕會根據(jù)當前的字數(shù)決定是否可用(字數(shù)超過 5 個字才可用)

(2)樣例代碼

Throttling 的作用

ThrottlingRxSwift 的一個特性。因為有時當一些東西改變時,通常會做大量的邏輯操作。而使用 Throttling 特性,不會產(chǎn)生大量的邏輯操作,而是以一個小的合理的幅度去執(zhí)行。比如做一些實時搜索功能時,這個特性很有用。

import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
     
    let disposeBag = DisposeBag()
     
    override func viewDidLoad() {
         
        //創(chuàng)建文本輸入框
        let inputField = UITextField(frame: CGRect(x:10, y:80, width:200, height:30))
        inputField.borderStyle = UITextBorderStyle.roundedRect
        self.view.addSubview(inputField)
         
        //創(chuàng)建文本輸出框
        let outputField = UITextField(frame: CGRect(x:10, y:150, width:200, height:30))
        outputField.borderStyle = UITextBorderStyle.roundedRect
        self.view.addSubview(outputField)
         
        //創(chuàng)建文本標簽
        let label = UILabel(frame:CGRect(x:20, y:190, width:300, height:30))
        self.view.addSubview(label)
         
        //創(chuàng)建按鈕
        let button:UIButton = UIButton(type:.system)
        button.frame = CGRect(x:20, y:230, width:40, height:30)
        button.setTitle("提交", for:.normal)
        self.view.addSubview(button)
         
         
        //當文本框內(nèi)容改變
        let input = inputField.rx.text.orEmpty.asDriver() // 將普通序列轉換為 Driver
            .throttle(0.3) //在主線程中操作,0.3秒內(nèi)值若多次改變,取最后一次
         
        //內(nèi)容綁定到另一個輸入框中
        input.drive(outputField.rx.text)
            .disposed(by: disposeBag)
         
        //內(nèi)容綁定到文本標簽中
        input.map{ "當前字數(shù):\($0.count)" }
            .drive(label.rx.text)
            .disposed(by: disposeBag)
         
        //根據(jù)內(nèi)容字數(shù)決定按鈕是否可用
        input.map{ $0.count > 5 }
            .drive(button.rx.isEnabled)
            .disposed(by: disposeBag)
    }
}

3,同時監(jiān)聽多個 textField 內(nèi)容的變化(textView 同理)

(1)效果圖

  • 界面上有兩個輸入框分別用于填寫電話的區(qū)號和號碼。
  • 無論那一個輸入框內(nèi)容發(fā)生變化,都會將它們拼成完整的號碼并顯示在 label 中。

(2)樣例代碼

import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
     
    let disposeBag = DisposeBag()
     
    @IBOutlet weak var textField1: UITextField!
    @IBOutlet weak var textField2: UITextField!
    @IBOutlet weak var label: UILabel!
     
    override func viewDidLoad() {
         
        Observable.combineLatest(textField1.rx.text.orEmpty, textField2.rx.text.orEmpty) {
            textValue1, textValue2 -> String in
            return "你輸入的號碼是:\(textValue1)-\(textValue2)"
            }
            .map { $0 }
            .bind(to: label.rx.text)
            .disposed(by: disposeBag)
    }
}

4,事件監(jiān)聽

(1)通過 rx.controlEvent 可以監(jiān)聽輸入框的各種事件,且多個事件狀態(tài)可以自由組合。除了各種 UI 控件都有的 touch 事件外,輸入框還有如下幾個獨有的事件:

  • editingDidBegin:開始編輯(開始輸入內(nèi)容)
  • editingChanged:輸入內(nèi)容發(fā)生改變
  • editingDidEnd:結束編輯
  • editingDidEndOnExit:按下 return 鍵結束編輯
  • allEditingEvents:包含前面的所有編輯相關事件

(2)下面代碼監(jiān)聽輸入框開始編輯事件(獲取到焦點)并做相應的響應。

textField.rx.controlEvent([.editingDidBegin]) //狀態(tài)可以組合
    .asObservable()
    .subscribe(onNext: { _ in
        print("開始編輯內(nèi)容!")
    }).disposed(by: disposeBag)

(3)下面代碼我們在界面上添加兩個輸入框分別用于輸入用戶名和密碼:

  • 如果當前焦點在用戶名輸入框時,按下 return 鍵時焦點自動轉移到密碼輸入框上。
  • 如果當前焦點在密碼輸入框時,按下 return 鍵時自動移除焦點。
import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
 
    //用戶名輸入框
    @IBOutlet weak var username: UITextField!
     
    //密碼輸入框
    @IBOutlet weak var password: UITextField!
     
    let disposeBag = DisposeBag()
     
    override func viewDidLoad() {
        super.viewDidLoad()
         
        //在用戶名輸入框中按下 return 鍵
        username.rx.controlEvent(.editingDidEndOnExit).subscribe(onNext: {
            [weak self] (_) in
            self?.password.becomeFirstResponder()
        }).disposed(by: disposeBag)
         
         //在密碼輸入框中按下 return 鍵
        password.rx.controlEvent(.editingDidEndOnExit).subscribe(onNext: {
            [weak self] (_) in
            self?.password.resignFirstResponder()
        }).disposed(by: disposeBag)
    }
}

附:UITextView 獨有的方法

(1)UITextView 還封裝了如下幾個委托回調(diào)方法:

  • didBeginEditing:開始編輯
  • didEndEditing:結束編輯
  • didChange:編輯內(nèi)容發(fā)生改變
  • didChangeSelection:選中部分發(fā)生變化

(2)使用樣例

import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
     
    let disposeBag = DisposeBag()
     
    @IBOutlet weak var textView: UITextView!
     
    override func viewDidLoad() {
         
        //開始編輯響應
        textView.rx.didBeginEditing
            .subscribe(onNext: {
                print("開始編輯")
            })
            .disposed(by: disposeBag)
         
        //結束編輯響應
        textView.rx.didEndEditing
            .subscribe(onNext: {
                print("結束編輯")
            })
            .disposed(by: disposeBag)
         
        //內(nèi)容發(fā)生變化響應
        textView.rx.didChange
            .subscribe(onNext: {
                print("內(nèi)容發(fā)生改變")
            })
            .disposed(by: disposeBag)
         
        //選中部分變化響應
        textView.rx.didChangeSelection
            .subscribe(onNext: {
                print("選中部分發(fā)生變化")
            })
            .disposed(by: disposeBag)
    }
}

RxSwift使用詳解系列
原文出自:www.hangge.com轉載請保留原文鏈接

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容