'How to change truncate characters in UILabel?

When the text of a UILabel gets truncated there are 3 dots inserted by default. Is it possible to change these characters or disable them?



Solution 1:[1]

Look at -[UILabel setLineBreakMode:] and UILineBreakModeCharacterWrap. The default value of -[UILabel lineBreakMode] is UILineBreakModeTailTruncation, which causes the ellipsis at the end.

Solution 2:[2]

As Javanator said you would have to do your own truncation. You shuld use the sizeWithFont:forWidth:lineBreakMode: message on the UIKit additions to NSString class to get the width of a string with a certain font. This will handle all types of fonts.

Link

Solution 3:[3]

You can also set

[lbl setAdjustsFontSizeToFitWidth:YES];

With this there will be no need of truncating text and you can display the complete text on your label.

Solution 4:[4]

I would like to provide a more Swifty version of what Fonix provided earlier and using Swift 5 syntax. Also I decided to write the functions as an extension of UILabel.

extension UILabel {
    func replaceEllipsis(withString replacement: String, andMaximumWidth width: CGFloat = 0) -> Bool {

        if let labelText = self.text, let font = self.font {
            let origSize = self.frame
            var useWidth = width

            if width <= 0 {
                useWidth = origSize.width // use label width by default if width <= 0
            }

            self.sizeToFit()
            let labelSize = labelText.size(withAttributes: [NSAttributedString.Key.font: font])

            if labelSize.width > useWidth {
                let truncateWidth = useWidth
                let subLength = labelText.count

                var newText = String(labelText[..<labelText.index(labelText.endIndex, offsetBy: -1)])
                newText = String(newText[..<newText.index(labelText.startIndex, offsetBy: getTruncatedStringPoint(splitPoint: subLength,
                                                                                                                  original: labelText,
                                                                                                                  truncatedWidth: truncateWidth,
                                                                                                                  font: font,
                                                                                                                  length: subLength))])
                newText = String.localizedStringWithFormat("%@%@", newText, replacement)
                var count = 0

                while newText.size(withAttributes: [NSAttributedString.Key.font: font]).width > useWidth {
                    count += 1
                    newText = String(labelText[..<labelText.index(labelText.endIndex, offsetBy: -(1 + count))])
                    newText = newText.trimmingCharacters(in: NSCharacterSet.whitespaces)
                    newText = String.localizedStringWithFormat("%@%@", newText, replacement)
                }
                self.text = newText
                self.frame = origSize
                return true
            } else {
                self.frame = origSize
                return false
            }
        } else {
            return false
        }
    }

    private func getTruncatedStringPoint(splitPoint: Int, original: String, truncatedWidth: CGFloat, font: UIFont, length: Int) -> Int {
        let index = original.index(original.startIndex, offsetBy: splitPoint)
        let splitLeft = String(original[..<index])

        let subLength = length / 2

        if subLength <= 0 {
            return splitPoint
        }

        let width = splitLeft.size(withAttributes: [NSAttributedString.Key.font: font]).width

        if width > truncatedWidth {
            return getTruncatedStringPoint(splitPoint: splitPoint - subLength, original: original, truncatedWidth: truncatedWidth, font: font, length: subLength)
        } else if width < truncatedWidth {
            return getTruncatedStringPoint(splitPoint: splitPoint + subLength, original: original, truncatedWidth: truncatedWidth, font: font, length: subLength)
        } else {
            return splitPoint
        }
    }
}

It'll be used as follows:

<UILabel>.replaceEllipsis(withString: " ...Read More") // if you want to use the label width

Also you can pass a custom width as well if you need to. I opted for the default width in the above example.

For references on what I used in my refactor, the below StackOverflow links were helpful:

Advanced by refactor

substringToIndex refactor

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Heath Borders
Solution 2
Solution 3 Girish
Solution 4 David Shi