Vvk
Vvk

Reputation: 4043

How to trim(remove) white spaces from end of a NSAttributedString

I have a string which has no whitespace at end of the string but when I am converting to NSAttributedString and set to UITextView it was seen some whitespace at end of the UILabel.

For making NSAttributedString I am using following code. In my code expectedLabelSize gives a big height.

UILabel *tempLbl = [[UILabel alloc]init];
tempLbl.font = txtView.font;
tempLbl.text = string;

NSDictionary *dictAttributes = [NSDictionary dictionaryWithObjectsAndKeys: tempLbl.font, NSFontAttributeName, aParaStyle, NSParagraphStyleAttributeName,[UIColor darkGrayColor],NSForegroundColorAttributeName, nil];

CGSize expectedLabelSize = [string boundingRectWithSize:maximumLabelSize options:NSStringDrawingUsesLineFragmentOrigin attributes:dictAttributes context: nil].size;

Upvotes: 16

Views: 6800

Answers (4)

Motti Shneor
Motti Shneor

Reputation: 2194

Here's an Obj-C rendering of @suhit Patil's Swift NSAttributedString extension - but this time, it's on NSMutableAttributedString and acts on self. Hope it'll be of use to someone.

@interface NSMutableAttributedString (OITTrimming)

- (void)trimWhiteSpace;

@end

@implementation NSMutableAttributedString (OITTrimming)

 /*!
  @abstract trims whitespacesAndNewlines off the receiver
*/
- (void)trimWhiteSpace {
    NSCharacterSet *legalChars = [[NSCharacterSet whitespaceAndNewlineCharacterSet] invertedSet];
    NSRange startRange = [self.string rangeOfCharacterFromSet: legalChars];
    NSRange endRange = [self.string rangeOfCharacterFromSet: legalChars options:NSBackwardsSearch];
    if (startRange.location == NSNotFound || endRange.location == NSNotFound) {
        // there are no legal characters in self --- it is ALL whitespace, and so we 'trim' everything leaving an empty string
        [self setAttributedString:[NSAttributedString new]];
    }
    else {
        NSUInteger startLocation = NSMaxRange(startRange), endLocation = endRange.location;
        NSRange range = NSMakeRange(startLocation - 1, endLocation - startLocation + 2);
        [self setAttributedString:[self attributedSubstringFromRange:range]];
    }
}

@end

Upvotes: 1

Michael Smirnov
Michael Smirnov

Reputation: 41

extension NSAttributedString {
    func trimmedAttributedString() -> NSAttributedString {
        let invertedSet = CharacterSet.whitespacesAndNewlines.inverted
        let startRange = string.rangeOfCharacter(from: invertedSet)
        let endRange = string.rangeOfCharacter(from: invertedSet, options: .backwards)
        guard let startLocation = startRange?.lowerBound, let endLocation = endRange?.lowerBound else {
            return self
        }
        let range = NSRange(startLocation...endLocation, in: string)
        return attributedSubstring(from: range)
    }
}

Upvotes: 4

Suhit Patil
Suhit Patil

Reputation: 12023

Swift 4 and above

we can create extension on NSMutableAttributedString which returns new NSAttributedString by removing .whitespacesAndNewlines

extension NSMutableAttributedString {

    func trimmedAttributedString() -> NSAttributedString {
        let invertedSet = CharacterSet.whitespacesAndNewlines.inverted
        let startRange = string.rangeOfCharacter(from: invertedSet)
        let endRange = string.rangeOfCharacter(from: invertedSet, options: .backwards)
        guard let startLocation = startRange?.upperBound, let endLocation = endRange?.lowerBound else {
            return NSAttributedString(string: string)
        }
        let location = string.distance(from: string.startIndex, to: startLocation) - 1
        let length = string.distance(from: startLocation, to: endLocation) + 2
        let range = NSRange(location: location, length: length)
        return attributedSubstring(from: range)
    }
}

Upvotes: 11

Dean
Dean

Reputation: 1542

Swift answer but it give you a start if you translate it to Obj-C (or make a swift file just with the extension for use in your Obj-C then)

extension NSMutableAttributedString {

    func trimmedAttributedString(set: CharacterSet) -> NSMutableAttributedString {

        let invertedSet = set.inverted

        var range = (string as NSString).rangeOfCharacter(from: invertedSet)
        let loc = range.length > 0 ? range.location : 0

        range = (string as NSString).rangeOfCharacter(
                            from: invertedSet, options: .backwards)
        let len = (range.length > 0 ? NSMaxRange(range) : string.characters.count) - loc

        let r = self.attributedSubstring(from: NSMakeRange(loc, len))
        return NSMutableAttributedString(attributedString: r)
    }
}

Usage :

let noSpaceAttributedString =
   attributedString.trimmedAttributedString(set: CharacterSet.whitespacesAndNewlines)

Upvotes: 25

Related Questions