skip to Main Content

I have a font which is super skinny. In photoshop, I have added stroke to the font which makes it look more appealing. When transferring it to iOS I couldn’t add a stroke unless I used NSAttributedString. By using the NSAttributedString I got one of my UILabels to look exactly how it looks in photoshop however the issue is that I will have hundreds of UILabels by the time my app is finished. Is there a way where I don’t have to manually connect each UILabel to its respective controller and set its attributedText one by one. Any suggestions would help.

3

Answers


  1. Based on @AdamPro13 suggestion, you could create a protocol extension for your NSAttributedString:

    So, create NSAttributedStringExtension.swift with something like that:

    protocol NSAttributedStringExtension {
        static func attributed(string:String, font:UIFont, color:UIColor) -> NSAttributedString
    }
    
    extension NSAttributedString : NSAttributedStringExtension {
        class func attributed(string:String, font:UIFont, color:UIColor) -> NSAttributedString {
    
            let attrs = [NSFontAttributeName:font, NSForegroundColorAttributeName:color]
            return NSAttributedString(string: string, attributes: attrs)
        }
    }
    

    And you could make several different functions for different label types.
    Just apply then on your label (rough code):

    let label:UILabel
    let font:UIFont
    let color:UIColor
    label.attributedText = NSAttributedString.attributed("test", font: font, color: color)
    

    Note: the font and colour you could setup in your protocol extension function

    Login or Signup to reply.
  2. If you’re using storyboard and want to use UILabels as normal, then you can try creating a UILabel subclass as shown below and using it in your storyboards as a custom class. This will effectively replace the text with the attributedText you want although you wont see it until runtime.

    class CustomLabel: UILabel {
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            commonInit()
        }
    
        func commonInit() {
            let attrs = [NSFontAttributeName: UIFont.boldSystemFontOfSize(19),
                         NSForegroundColorAttributeName: UIColor.blueColor()]
            attributedText = NSAttributedString(string: text!, attributes: attrs)
        }
    }
    
    Login or Signup to reply.
  3. I was just searching and then I stumbled upon this question. I think you want a category for UILabel. I have one very helpful method from my old Cocoapod library called GPKit https://github.com/glennposadas/gpkit-ios that I made before. But this code below is updated and documented.

    import UIKit
    
    /// Category for UILabel helper functions
    extension UILabel {
        /// A helper function for setting up the normal properties of the label.
        /// This means that the label has no special attributes.
        /// This uses the system font.
        func setup(_ text: String, fontSize: CGFloat, weight: UIFont.Weight = .regular, italic: Bool = false, textColor: UIColor = .lalaDarkGray, numberOfLines: Int = 1, textAlignment: NSTextAlignment = .natural) {
            self.font = italic ? UIFont.italicSystemFont(ofSize: fontSize) : UIFont.systemFont(ofSize: fontSize, weight: weight)
            self.text = text
            self.textColor = textColor
            self.numberOfLines = numberOfLines
            self.textAlignment = textAlignment
        }
    
        /**
         Sets up the label with two different kinds of attributes in its attributed text.
    
         - Author: Glenn
    
         - Important:
             - primaryString = "Total:"
             - secondaryString = "123"
             - This means that the function will concat the secondary string into the primary string and highlights the secondary string.
             - Using the highlightedText means the highlightedText itself is in the primaryString.
    
         - parameters:
            - primaryString: the normal attributed string.
            - secondaryString: the bold or highlighted string.
            - highlightedText: this one is like the secondary string, if this is provided, then the secondaryString is ignored. This is to be used if the highlighted text is not to be concatinated at the end of the primaryString
         */
        func setAttributedText(
            primaryString: String,
            textColor: UIColor,
            font: UIFont,
            secondaryString: String = "",
            secondaryTextColor: UIColor? = nil,
            secondaryFont: UIFont? = nil,
            highlightedText: String? = nil,
            textAlignment: NSTextAlignment = .center,
            numberOfLines: Int = 1,
            lineHeightMultiple: CGFloat = 1) {
    
            var textToBeHighlighted = ""
            var completeString: String!
    
            self.numberOfLines = numberOfLines
    
            if let highlightedText = highlightedText {
                textToBeHighlighted = highlightedText
                completeString = primaryString
            } else {
                if secondaryString.hasValidValue() {
                    textToBeHighlighted = secondaryString
                    completeString = "(primaryString) (secondaryString)"
                } else {
                    completeString = primaryString
                }
            }
    
            let paragraphStyle = NSMutableParagraphStyle()
            paragraphStyle.alignment = textAlignment
            paragraphStyle.lineHeightMultiple = lineHeightMultiple
    
            let completeAttributedString = NSMutableAttributedString(
                string: completeString, attributes: [
                    .font: font,
                    .foregroundColor: textColor,
                    .paragraphStyle: paragraphStyle
                ]
            )
    
            let secondStringAttribute: [NSAttributedString.Key: Any] = [
                .font: secondaryFont ?? font,
                .foregroundColor: secondaryTextColor ?? textColor,
                .paragraphStyle: paragraphStyle
            ]
    
            let range = (completeString as NSString).range(of: textToBeHighlighted)
    
            completeAttributedString.addAttributes(secondStringAttribute, range: range)
    
            self.attributedText = completeAttributedString
        }
    }
    

    You can use it in every label you have like so:

    internal lazy var label_Total: UILabel = {
        let label = UILabel()
        label.setAttributedText(
            primaryString: "Total".localized(),
            textColor: .gray,
            font: UIFont.systemFont(ofSize: 14.0),
            secondaryString: "",
            secondaryTextColor: .blue,
            secondaryFont: UIFont.systemFont(ofSize: 14.0, weight: customFontWeight)
        )
        return label
    }()
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search