Chris Hansen
Chris Hansen

Reputation: 8657

How to strikethrough a portion of the text

I want to strike through the price, like this.

Buy this course for $19.99, $5.99

Notice how only the $19.99 is strike through? How can I do this using UILabel and Swift?

Here's what I have so far?

extension String {
    func strikeThrough() -> NSAttributedString {
        let attributeString =  NSMutableAttributedString(string: self)
        attributeString.addAttribute(
            NSAttributedString.Key.strikethroughStyle,
               value: NSUnderlineStyle.single.rawValue,
                   range:NSMakeRange(0,attributeString.length))
        return attributeString
    }
}

Upvotes: 2

Views: 2594

Answers (3)

Mazharul Belal
Mazharul Belal

Reputation: 105

Now the extension code has been updated. You should add the rawValue.

extension String {
        func createAttributedString(stringtToStrike: String) -> NSMutableAttributedString {
            let attributedString = NSMutableAttributedString(string: self)
            let range = attributedString.mutableString.range(of: stringtToStrike)
            attributedString.addAttributes([NSAttributedString.Key.strikethroughStyle : NSUnderlineStyle.single.rawValue], range: range)
            return attributedString
        } }

USE :

self.yourLabel.attributedText = "$19.99, $5.99".createAttributedString(stringToStrike: "$19.99")

Upvotes: 0

pua666
pua666

Reputation: 336

Attributed strings are quite a hassle to create indeed.

This clever code extends NSAttributedString with a .composing(_:) method, I found it on GitHub (see copyright notice at the bottom): https://github.com/vincent-pradeilles/NSAttributedStringBuilder. It uses result builders (nee function builders).

@_functionBuilder
public class NSAttributedStringBuilder {
    public static func buildBlock(_ components: NSAttributedString...) -> NSAttributedString {
        let result = NSMutableAttributedString(string: "")

        return components.reduce(into: result) { (result, current) in result.append(current) }
    }
}

extension NSAttributedString {
    public class func composing(@NSAttributedStringBuilder _ parts: () -> NSAttributedString) -> NSAttributedString {
        return parts()
    }
}

With this extension, you can build your attributed string like this:

let attributedString = NSAttributedString.composing {
    NSAttributedString(string: "Buy this course for ")
    NSAttributedString(string: "$19.99", attributes: [.strikethroughStyle : NSUnderlineStyle.single.rawValue])
    NSAttributedString(string: ", $5.99")
}

Then you assign the attributed string to the UILabel's attributedText property, of course.

This should be possible to use for any attribute.

Note that it will need to be updated for Swift 5.3 (I don't have it yet) since it predates the final nomenclature of the result builder language feature. So basically you'll need to replace @_functionBuilder with @resultBuilder if I'm not mistaken.

Since this is not my code and it's released under the MIT license, I guess I have to reprint the notice here:

MIT License

Copyright (c) 2019 Vincent Pradeilles

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

Upvotes: 1

Debashish Das
Debashish Das

Reputation: 919

extension String {
    func createAttributedString(stringtToStrike: String) -> NSMutableAttributedString {
        let attributedString = NSMutableAttributedString(string: self)
        let range = attributedString.mutableString.range(of: stringtToStrike)
        attributedString.addAttributes([NSAttributedString.Key.strikethroughStyle : NSUnderlineStyle.single], range: range)
        return attributedString
    }
}

USE :

self.yourLabel.attributedText = "$19.99, $5.99".createAttributedString(stringToStrike: "$19.99")

Upvotes: 2

Related Questions