So I have a UILabel with text which I have to write in UITextField for check are the characters of UILabel and UITextField are similar? So I have some practice in C-Lang and in C-lang to solve this we have to write Integer indices to compare the indices in "UILabel" from "UITextField". So we have a characters and if characters in label and textfield are the same we just increment an index and have to compare the next index(character).
I need to compare each character. For example, we have a string "Hello!". And if we write "Heklo?", our characters "H", "e", "l", "o" must be green and our "k" and "?" must be red.
In swift I tried to do the same but it doesnt work.
import UIKit
class ViewController: UIViewController {
private let textLabel: UILabel = {
let label = UILabel()
label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "There are a text, which you must text to get the last character of this label!"
label.sizeToFit()
return label
}()
private let resultTextLabel: UILabel = {
let label = UILabel()
label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping
label.translatesAutoresizingMaskIntoConstraints = false
label.sizeToFit()
return label
}()
private let textField : UITextField = {
let text = UITextField(frame: CGRect(x: 20, y: 300, width: 300, height: 40))
text.placeholder = "Enter text Here!"
text.font = .systemFont(ofSize: 15)
text.autocorrectionType = .no
text.keyboardType = .default
text.returnKeyType = .done
text.clearButtonMode = .whileEditing
text.addTarget(self, action: #selector(checkWrongOrRight), for: .editingChanged)
return text
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(textLabel)
view.addSubview(textField)
view.addSubview(resultTextLabel)
setUpConstraints()
}
@objc func checkWrongOrRight(_ textField: UITextField) {
// ??????????????? I thought that a logic of app could be here
if textLabel.text == resultTextLabel.text {
textLabel.textColor = .green
} else {
textLabel.textColor = .red
}
}
func setUpConstraints() {
textLabel.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 20).isActive = true
textLabel.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -20).isActive = true
textLabel.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 100).isActive = true
resultTextLabel.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 20).isActive = true
resultTextLabel.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -20).isActive = true
resultTextLabel.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 500).isActive = true
}
}
So how can I compare characters in UILabel and in UITextField?
One way to do this is to get the length of the typed text and compare that to the substring of the expected text of the same length:
@objc func checkWrongOrRight(_ textField: UITextField) {
guard let text = textLabel.text,
let input = textField.text
else {
textLabel.textColor = .red
return
}
if input == text.prefix(input.count) {
textLabel.textColor = .green
} else {
textLabel.textColor = .red
}
}
Edit
Since the actual question is about colouring individual characters depending on whether they match or not:
You can use Attributed strings for this, getting the ranges of characters that in incorrect and applying the red colour as an attribute to these ranges:
Define this helper function in your view controller
// helper function that returns an attributed string to display
func displayString(input: String?, expected: String?) -> NSAttributedString {
guard let input = input,
let expected = expected
else {
return NSAttributedString(string: "")
}
// Get an array of NSRange objects of incorrect characters
let errorRanges = zip((0...), zip(input, expected).map(==)).filter { !$1 }.map { NSRange(location: $0.0, length: 1) }
// Set the default colour
let attString = NSMutableAttributedString(string: input, attributes: [.foregroundColor: UIColor.green])
// Set the colour for incorrect characters to red
errorRanges.forEach { range in
attString.addAttribute(.foregroundColor, value: UIColor.red, range: range)
}
return attString
}
And you can use it as
@objc func checkWrongOrRight(_ textField: UITextField) {
textField.attributedText = displayString(input: textField.text, expected: textLabel.text)
}
This colours the incorrect characters.
There are optimisations that can be made - such as converting the current 1 character length ranges to a single range where consecutive characters are incorrect.