Use of UI control UITextField and UITextView extension of RxSwift

1, Listen for changes in the contents of a single textField (the same applies to textView)

  • Display the contents entered in textField to the console in real time. Example code:
// Create text entry box
let textField = UITextField(frame: CGRect(x:10, y:80, width:200, height:30))
textField.borderStyle = UITextField.BorderStyle.roundedRect
self.view.addSubview(textField)
 
// When the content of the text box changes, the content is output to the console
textField.rx.text.orEmpty.asObservable()
    .subscribe(onNext: {
        print("You entered:\($0)")
    })
    .disposed(by: disposeBag)
  • . orEmpty can set String? The ControlProperty of type is converted to String to avoid unpacking again.
  • The effects are as follows:

You entered: 1
 You entered: 12
 You entered: 123
 You entered: 1234
 You entered: 12345
 You entered: 123456
 You entered: 1234567
 You entered: 12345678
 You entered: 123456789
 You entered: 1234567890

2, Bind content to other controls

  • Desired effects:
    • Display the contents entered in the first textField to the second textField in real time;
    • At the same time, the current number of words will be displayed in label in real time;
    • The "submit" button at the bottom will determine whether it is available according to the current number of words (only when the number of words exceeds 5).
  • Example code:
let disposeBag = DisposeBag()
// Create text entry box
let inputField = UITextField(frame: CGRect(x:50, y:80, width:200, height:30))
inputField.borderStyle = UITextField.BorderStyle.roundedRect
self.view.addSubview(inputField)
         
// Create text output box
let outputField = UITextField(frame: CGRect(x:50, y:150, width:200, height:30))
outputField.borderStyle = UITextField.BorderStyle.roundedRect
self.view.addSubview(outputField)
 
// Create text label
let label = UILabel(frame:CGRect(x:60, y:190, width:300, height:30))
self.view.addSubview(label)
 
// Create button
let button:UIButton = UIButton(type:.system)
button.frame = CGRect(x:60, y:230, width:40, height:30)
button.setTitle("Submit", for:.normal)
self.view.addSubview(button)
 
// When the content of the text box changes
let input = inputField.rx.text.orEmpty.asDriver() // Convert normal sequence to Driver
    .throttle(0.3) // Operate in the main thread. If the value changes many times within 0.3 seconds, take the last time
 
// Bind content to another input box
input.drive(outputField.rx.text)
    .disposed(by: disposeBag)
 
// Bind content to text labels
input.map{ "Current number of words:\($0.count)" }
    .drive(label.rx.text)
    .disposed(by: disposeBag)
 
// Determine whether the button is available according to the number of words in the content
input.map{ $0.count > 5 }
    .drive(button.rx.isEnabled)
    .disposed(by: disposeBag)
  • Operation effect:


  • Throttling is a feature of RxSwift, because when something changes, it usually does a lot of logical operations. Using the throttling feature will not produce a large number of logical operations, but will be performed in a small and reasonable range. For example, this feature is very useful when doing some real-time search functions.

3, Monitor the content changes of multiple textfields at the same time (the same is true for textView)

  • Desired effects:
    • There are two input boxes on the interface, which are used to fill in the area code and number of the telephone respectively;
    • No matter which input box changes, they will be spelled into a complete number and displayed in the label.
  • Example code:
let disposeBag = DisposeBag()
// Create text entry box
let inputField = UITextField(frame: CGRect(x:50, y:80, width:200, height:30))
inputField.borderStyle = UITextField.BorderStyle.roundedRect
self.view.addSubview(inputField)
         
// Create text output box
let outputField = UITextField(frame: CGRect(x:50, y:150, width:200, height:30))
outputField.borderStyle = UITextField.BorderStyle.roundedRect
self.view.addSubview(outputField)
 
// Create text label
let label = UILabel(frame:CGRect(x:60, y:190, width:300, height:30))
self.view.addSubview(label)

Observable.combineLatest(inputField.rx.text.orEmpty, outputField.rx.text.orEmpty) {
            textValue1, textValue2 -> String in
            return "The number you entered is:\(textValue1)-\(textValue2)"
            }
            .map { $0 }
            .bind(to: label.rx.text)
            .disposed(by: disposeBag)
  • Operation effect:

4, Event listening

  • Various events in the input box can be monitored through rx.controlEvent, and multiple event states can be combined freely. In addition to the touch events of various UI controls, the input box also has the following unique events:
    • editingDidBegin: start editing (start entering content)
    • editingChanged: the input content has changed
    • editingDidEnd: end editing
    • editingDidEndOnExit: press the return key to end editing
    • allEditingEvents: contains all previous editing related events
  • Listen to the input box to start editing the event (get the focus) and respond accordingly:
textField.rx.controlEvent([.editingDidBegin]) //States can be combined
    .asObservable()
    .subscribe(onNext: { _ in
        print("Start editing content!")
    }).disposed(by: disposeBag)
  • Add two input boxes on the interface to input user name and password respectively:
    • If the current focus is in the user name input box, the focus will automatically shift to the password input box when you press the return key;
    • If the current focus is in the password input box, the focus will be automatically removed when you press the return key.
// Press the return key in the user name input box
username.rx.controlEvent(.editingDidEndOnExit).subscribe(onNext: {
	[weak self] (_) in
	self?.password.becomeFirstResponder()
}).disposed(by: disposeBag)
         
// Press the return key in the password input box
password.rx.controlEvent(.editingDidEndOnExit).subscribe(onNext: {
	[weak self] (_) in
	self?.password.resignFirstResponder()
}).disposed(by: disposeBag)

5, UITextView specific methods

  • UITextView also encapsulates the following delegate callback methods:
    • Didbiginediting: start editing
    • didEndEditing: end editing
    • didChange: the editing content has changed
    • didChangeSelection: the selected part changes
  • Use example:
// Start editing response
textView.rx.didBeginEditing
    .subscribe(onNext: {
        print("Start editing")
    })
    .disposed(by: disposeBag)
 
// End editing response
textView.rx.didEndEditing
    .subscribe(onNext: {
        print("End editing")
    })
    .disposed(by: disposeBag)
 
// Content change response
textView.rx.didChange
    .subscribe(onNext: {
        print("Content changes")
    })
    .disposed(by: disposeBag)
 
// Select partial change response
textView.rx.didChangeSelection
    .subscribe(onNext: {
        print("The selected part changes")
    })
    .disposed(by: disposeBag)

Added by shahab03 on Sun, 31 Oct 2021 15:50:17 +0200