изменение стиля следующего абзаца с помощью typingAttributes

#ios #swift #macos #textkit

#iOS #swift #macos #textkit

Вопрос:

Я работаю над приложением для iOS. В приложении у меня есть UITextView место, где пользователь должен вводить несколько абзацев приписываемого текста. Мое требование — изменять стиль следующего абзаца каждый раз, когда пользователь нажимает Enter .

Итак, я реализовал следующую функцию делегирования TextView:

 func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    if (text == "n") {
        textView.typingAttributes = [NSMutableAttributedString.Key.paragraphStyle: self.paragraphStyle]
    }
    return true
}
 

Проблема заключается в:

Стиль следующего абзаца изменяется, но не сразу после нажатия Enter. Вместо этого сначала возвращается новая строка со старым стилем, а когда пользователь снова нажимает Enter, стиль абзаца изменяется.

Пример:

Полный код:

 import UIKit

class ViewController: UIViewController, UITextViewDelegate {
    @IBOutlet weak var textView: UITextView!    
    // Create paragraph styles
    let paragraphStyle = NSMutableParagraphStyle()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        textView.delegate = self
        
        // Create paragraph style
        self.paragraphStyle.firstLineHeadIndent = 140
        // Create attributed string
        let string = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"
        // Create attributed string
        let myAttrString = NSMutableAttributedString(string: string, attributes: [:])
        // Write it to text view
        textView.attributedText = myAttrString
    }

    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        if (text == "n") {
            textView.typingAttributes = [NSMutableAttributedString.Key.paragraphStyle: self.paragraphStyle]
        }
        return true
    }
}
 

Ответ №1:

Я думаю shouldChangeTextIn , что способ работает так же, как работает проверка орфографии или автозамена. Когда вы впервые вводите слово с ошибкой, оно не заменяется, пока вы не нажмете пробел. Аналогично, shouldChangeTextIn первоначально подтверждается n , когда вы вводите его, но замена не происходит до тех пор, пока не будет инициирован ввод следующего.

Вместо этого вы можете использовать метод textViewDidChange экземпляра, который относится к тому же UITextViewDelegate протоколу:

 func textViewDidChange(_ textView: UITextView) {
    if (textView.text.last == "n") {
        textView.typingAttributes = [NSMutableAttributedString.Key.paragraphStyle: self.paragraphStyle]
    }
}