how can I check if a text in a UILabel went to a new line? I want to count the times when a text moved to a new line in order to get the distance between this line and the top of the UILabel. An easier way would be to get the number of the line which contains a certain word, but I couldn't find an answer for that. Do you know how to achieve it?
EDIT:
What I want to do is to add UITextFields into a label. I want the UITextFields to cover specific words, but the text in the label will change so the UITextField has to be dynamic. I already works, but only with the first line since in the UITextField, I can tap into the .firstBaselineAnchor property.
It works with this code here:
let labelView = UILabel(frame: .zero)
labelView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(labelView)
NSLayoutConstraint.activate([
labelView.leadingAnchor.constraint(equalTo: self.cardView.leadingAnchor, constant: 10),
labelView.trailingAnchor.constraint(equalTo: self.cardView.trailingAnchor, constant: -10),
labelView.topAnchor.constraint(equalTo: self.cardView.topAnchor, constant: 10)
])
self.labelView = labelView
let text = "This labelview ______ created to test how to replace the underscores with a textinput."
labelView.text = text
let font = UIFont.systemFont(ofSize: 30)
labelView.font = font
let distanceOfCharacterToStringStart = labelView.text?.characterPosition(character: "_", with: font)
labelView.textAlignment = .left
labelView.numberOfLines = 0
// getCharacterAtPosition(of: text, with: font, in: labelView.frame.width)
//MARK: - UITEXTFIELD
let textField = UITextField(frame: .zero)
textField.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(textField)
NSLayoutConstraint.activate([
textField.leadingAnchor.constraint(equalTo: labelView.leadingAnchor, constant: distanceOfCharacterToStringStart!.x - 0.5),
textField.trailingAnchor.constraint(equalTo: labelView.trailingAnchor),
textField.bottomAnchor.constraint(equalTo: labelView.firstBaselineAnchor, constant: 0 - labelView.font.descender),
textField.heightAnchor.constraint(equalToConstant: labelView.font.lineHeight)
])
self.labelView = labelView
textField.backgroundColor = UIColor.red
(I know that I still have to fix the trailing constraint of the UITextView.) It calculates the distance between the beginning of the string and the first underscore character by using this method:
extension StringProtocol {
func characterPosition(character: Character, with font: UIFont) -> CGPoint? {
guard let index = firstIndex(of: character) else {
print("\(character) is missed")
return nil
}
let string = String(self[..<index])
let size = string.size(withAttributes: [.font: font])
return CGPoint(x: size.width, y: 0)
}
}
But now I want to get it to work for the other lines in between the first and last baseline as well. So I thought I would probably have to calculate where the text goes into the next line, and then I could substring it and again calculate the distance of the first character of the string in this line and the underscore in this line (if it exists) by using a similar method as shown above. Here is what I started creating in order to do so:
func getCharacterAtPosition(of string: String, with font: UIFont, in labelsize: CGFloat) -> [Character : Int] {
var characterAtIndex: [Character : Int] = [:]
var indexCount = 0
for c in string {
let upperBound = String.Index.init(utf16Offset: indexCount, in: string)
let partOfFullString = String(string[..<upperBound])
let size = partOfFullString.size(withAttributes: [.font: font])
if size.width >= labelsize {
characterAtIndex = [c : indexCount]
indexCount = 0
break
} else {
indexCount += 1
}
}
return characterAtIndex
}
By counting the number of new lines and the distance of a character to the first character in each line, I could get the coordinates for my UITextView.