Home > Software engineering >  How to refactor attributedText in Swift using different loops?
How to refactor attributedText in Swift using different loops?

Time:02-10

func attributedText() -> NSAttributedString {
    let string = termsTextView.text as NSString
    let attributedString = NSMutableAttributedString(
        string: string as String,
        attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 15.0)]
    )
    let boldFontAttribute = [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 15.0)]
    let semiBoldFontAttribute = [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 12.0)]
    attributedString.addAttributes(boldFontAttribute, range: string.range(of: "You"))
    attributedString.addAttributes(boldFontAttribute, range: string.range(of: "Services."))
    attributedString.addAttributes(boldFontAttribute, range: string.range(of: "1. OVERVIEW."))
    attributedString.addAttributes(boldFontAttribute, range: string.range(of: "II. TERMS AND CONDITIONS"))
    attributedString.addAttributes(semiBoldFontAttribute, range: string.range(of: "A. Adults & Children."))
    attributedString.addAttributes(boldFontAttribute, range: string.range(of: "18 Years Old and Older"))
    attributedString.addAttributes(boldFontAttribute, range: string.range(of: "Under 18 Years Old"))
    attributedString.addAttributes(semiBoldFontAttribute, range: string.range(of: "B. Availability"))
    attributedString.addAttributes(semiBoldFontAttribute, range: string.range(of: "C. Authorized Use"))
    attributedString.addAttributes(semiBoldFontAttribute, range: string.range(of: "D. Linking (To & From) the Website; Advertisers"))
    attributedString.addAttributes(semiBoldFontAttribute, range: string.range(of: "E. Privacy Policy"))
    attributedString.addAttributes(semiBoldFontAttribute, range: string.range(of: "F. Prohibition against Harmful Transmissions & Appropriate Use of Website"))
    attributedString.addAttributes(boldFontAttribute, range: string.range(of: "User Content"))
    attributedString.addAttributes(semiBoldFontAttribute, range: string.range(of: "G. Disclaimer of Warranties; Limitation Of Liability"))
    attributedString.addAttributes(semiBoldFontAttribute, range: string.range(of: "I. Indemnification"))
    attributedString.addAttributes(semiBoldFontAttribute, range: string.range(of: "J. Severability"))
    attributedString.addAttributes(semiBoldFontAttribute, range: string.range(of: "K. Entire Agreement & Priority"))
    attributedString.addAttributes(semiBoldFontAttribute, range: string.range(of: "L. Choice Of Law"))
    attributedString.addAttributes(semiBoldFontAttribute, range: string.range(of: "M. Venue; Personal Jurisdiction; Service of Process"))
    attributedString.addAttributes(semiBoldFontAttribute, range: string.range(of: "N. Headings For Convenience Only"))
    attributedString.addAttributes(semiBoldFontAttribute, range: string.range(of: "O. Waiver"))
    attributedString.addAttributes(semiBoldFontAttribute, range: string.range(of: "Q. Copyright Complaints"))
    attributedString.addAttributes(semiBoldFontAttribute, range: string.range(of: "R. Contact"))
    attributedString.addAttributes(semiBoldFontAttribute, range: string.range(of: "S. Local Laws"))
    attributedString.addAttributes(semiBoldFontAttribute, range: string.range(of: "T. Prohibited Conduct"))
    return attributedString
}

This is my code to set attributedText on UITextView I am trying to refactor using different loops to remove repeated code as much as possible. like using enum or switch Case Any idea how can i achieve this? Thanks in

CodePudding user response:

Whatever approach you go for is going to be reasonably verbose as somehow you need to get all the text in there. This approach might be slightly nicer (assumes you are only looking for one occurence of each, as this is what the above achieves):

let boldText = ["You", "Services.", "1. Overview", ...]

boldText.forEach{
   attributedString.addAttributes(semiBoldFontAttribute, range: string.range(of: $0}
}

and the same for the other attributes.

IMO it's slightly more elegant, and it would mean you could move the arrays out into their own file and treat them as constants. eg.

enum LookupTexts {
   static let boldText = ["You", "Services.", "1. Overview", ...]
   static let semiBoldText = [...]
}

which would make the call site

LookupTexts.boldText.forEach{
   attributedString.addAttributes(semiBoldFontAttribute, range: string.range(of: $0}

There is a problem with this and the original - what happens if the text doesn't exist? You'd be better checking for the range of the text in an if let and then only apply the attribute it if you have a resulting valid range.

  • Related