Search code examples
iosswiftxcodetextview

How to change font style in textview from cursor point onwards, not entire textview - Swift


I'm working on a barebones text editor, and I've run into an issue. I have two buttons at the top of the app: Bold and Italic. While I have already figured out how to make these buttons alter the text being entered into the textview, they change everything written in the view, including things already written. So hitting "Italic" will italicize everything in the view. I'm wanting more along the lines of "I'm hitting italicize -- oh cool now I'm writing in italics. Now I'm hitting it again-- and it's normal again."

I know this issue is stemming from the buttons changing the font the whole view is using, I just can't figure out the correct way to be doing this.

Here's my code so far:

@IBAction func italicizeHit(_ sender: Any) {
        if isItalics == false {
            textView.font = UIFont.italicSystemFont(ofSize: 15)}
        else{
            isItalics == false;
            textView.font = UIFont.systemFont(ofSize: 15)
        }
    }

I also can't quite figure out what to set the textView.font to in order to return it to its normal state, but that's a more secondary problem. I'm mostly interested in correctly toggling italicize.


Solution

  • The issue here is that textView.font sets all of the textView's text to that property.

    In order to achieve multiple styles, you're going to need to use a NSAttributedString (which can store bold, italic, and regular text all in the same string) rather than just a plain String.

    The good news, a textView can easily take a NSAttributedString instead of a regular String. In order to change properties, use the typingAttributes property of the textView. This will change the style of any new text typed and not the entire textView. Here's an example:

    class ViewController: UIViewController {
    
        let textView: UITextView  // initialize textView either via storyboard or code
        let attributesBold = [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16, weight: .bold)]
        let attributesNormal = [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16, weight: .regular)]
        
        override func viewDidLoad() {
            textView.attributedText = NSAttributedString(string: "")
            textView.typingAttributes = attributesNormal
        }
    
        @IBAction func boldTapped(_ sender: Any) {
            textView.typingAttributes = attributesBold
        }
    }