-1

I am creating an array of String(s) to use with the titleForFooterInSection table view delegate method. Each String will span over several lines and some of the words need to be emphasised.

How can I have only selected words of a string have a bold typeface?

I would like to achieve what is in this picture: table view footer with bold

Thank you

NotationMaster
  • 390
  • 3
  • 17
  • `NSAttributedString` is perfectly capable of being stored in arrays. – Gereon Aug 25 '19 at 16:48
  • How do I then change only some selected words of a given string into bold typeface? I have found this question: https://stackoverflow.com/questions/12974120/nsattributedstring-change-style-to-bold-without-changing-pointsize but the `rangeOfString` is not available for NSMutableAttributedStrings. – NotationMaster Aug 25 '19 at 16:49
  • Why has this been downvoted? What is wrong with it? – NotationMaster Aug 25 '19 at 18:18

1 Answers1

1

What I did in some project is that I created an object like so:

struct StringWithStyle {
    let font: UIFont
    let color: UIColor
    let text: String
    let backgroundcolor: UIColor

    init(font: UIFont,
         color: UIColor,
         text: String,
         backgroundColor: UIColor = .clear) {
        self.font = font
        self.color = color
        self.text = text
        self.backgroundcolor = backgroundColor
    }

    var mutableAttrString: NSMutableAttributedString {
        let attributes = [NSAttributedString.Key.font: font,
                          NSAttributedString.Key.foregroundColor: color,
                          NSAttributedString.Key.backgroundColor: backgroundcolor]
        return NSMutableAttributedString(string: text, attributes: attributes)
    }
}

You can of course set the font to stay same or create common styles used in your app.

Then I have and extension to pass the text with the styles

static func textWithMultipleStyles(_ styles: [StringWithStyle]) -> NSMutableAttributedString {
    var allTextStyles = styles
    let text = allTextStyles.removeFirst().mutableAttrString
    guard !allTextStyles.isEmpty else {
        return text
    }
    for nextText in allTextStyles {
        text.append(nextText.mutableAttrString)
    }
    return text
}

And to use you:

let example = String.textWithMultipleStyles([StringWithStyle(font: UIFont.boldSystemFont(ofSize: 16.0),
                                                      color: .black,
                                                      text: "First String"),
                                          StringWithStyle(font: UIFont.systemFont(ofSize: 13, weight: .semibold),
                                                      color: .red,
                                                      text: "Second string")])

Maybe there is better way, but for me like this I have 3-4 common styles used in the app and can construct multiple style strings easily.

Else you can use ranges

let boldText = "Some bold text"
let message = "This is a sentence with bold text \(boldText)"
let range = (message as NSString).rangeOfString(boldText)
let attributedString = NSMutableAttributedString(string: message)
attributedString.addAttribute(NSFontAttributeName, value: UIFont.boldSystemFontOfSize(label.font.pointSize), range: range)
label.attributedText = attributedString
Andreas777
  • 377
  • 1
  • 3
  • 14
  • Where does the `StringStyle` type comes from? How do you then apply this method to a part of selected part of a string? – NotationMaster Aug 25 '19 at 17:21
  • Yes sorry. Should be everywhere StringWithStyle. I changed and added an example – Andreas777 Aug 25 '19 at 17:31
  • Thanks! This is interesting but I am not sure I will be able to use it because I would like to keep the app accessible, that is using the `.preferredFontStyle(for:)`... This text will be in the footer of a grouped table view and each footer will have several lines, among which some words will have to be bold. I don't know if this makes it clearer. – NotationMaster Aug 25 '19 at 17:34
  • 1
    Then you have to go with ranges of specific words, which I don't like that much to use in code. This way maybe it makes the construction of strings to take more lines, but it is more straightforward, at least for me, and easier to debug and change later. – Andreas777 Aug 25 '19 at 17:40
  • I really like your method, I really do, but as soon as an user would change the text size, things would become broken. How can I do the other approach? – NotationMaster Aug 25 '19 at 17:41
  • I have added a picture to the question to show what I want to achieve. That is from the Accessibility menu in Settings on iPhone – NotationMaster Aug 25 '19 at 20:16
  • 1
    I think my answer works for it and I don't understand the problem with preferredFontStyle. And the range answer also should work. – Andreas777 Aug 26 '19 at 10:32
  • Thanks, I have marked it as correct and I trust you. I will see tonight if I can make it work in my situation. – NotationMaster Aug 26 '19 at 10:33
  • It's not that is correct. There are many ways to do it. Because I used a lot different styles even in one string that works for me. I also didn't downvote you and don't know why someone downvoted your question. – Andreas777 Aug 26 '19 at 10:37
  • Thanks! I will fiddle with your proposed solutions as I need to come up with a function that, called with the main string and optional extra strings as arguments will create a new attributed string to put inside the array. Otherwise it will be 20.000 lines of code for this. Next issue: `footerForSection` returns `String?` not `NSAttributedString` so I wonder if I will lose the formatting when I convert it back... – NotationMaster Aug 26 '19 at 10:41
  • I assumed that you use a custom UIView in viewForFooterInSection and didn't notice the titleForFooterInSection. Even though you can convert it to string again. attributedText.string or something like this – Andreas777 Aug 26 '19 at 10:43
  • I was thinking about `viewForFooterInSection` but I have never used it before and I have 16 sections, each one with different footer so I came here to ask for guidance. Thank you for being the only one who did his best to help (and didn't downvote a question that is not covered elsewhere in modern Swift language). – NotationMaster Aug 26 '19 at 10:51
  • If they are using just a label with text like the sample image, then they are not so different and you can reuse just one custom view with a UILabel inside. The question about making part of string bold is covered in other posts and someone can assume you didn't try anything before posting and downvote. – Andreas777 Aug 26 '19 at 10:54
  • True ... that's why I was asking specifically: "how to make the text of a UITableView's footer bold". Apple's Documentation is very vague on all this and it is a continuous hit or miss. But yes, I should learn to just destroy my head before posting anything here, it is very stressful otherwise... – NotationMaster Aug 26 '19 at 11:04
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/198480/discussion-between-andreas777-and-notationmaster). – Andreas777 Aug 26 '19 at 11:06