I am trying to make a simple Coffee Calculator. I need to display the amount of coffee in grams. The "g" symbol for grams needs to be attached to my UILabel that I am using to display the amount. The numbers in the UILabel are changing dynamically with user input just fine, but I need to add a lower case "g" on the end of the string that is formatted differently from the updating numbers. The "g" needs to be attached to the numbers so that as the number size and position changes, the "g" "moves" with the numbers. I'm sure this problem has been solved before so a link in the right direction would be helpful as I've googled my little heart out.

I've searched through the documentation for an attributed string and I even downloded an "Attributed String Creator" from the app store, but the resulting code is in Objective-C and I am using Swift. What would be awesome, and probably helpful to other developers learning this language, is a clear example of creating a custom font with custom attributes using an attributed string in Swift. The documentation for this is very confusing as there is not a very clear path on how to do so. My plan is to create the attributed string and add it to the end of my coffeeAmount string.

var coffeeAmount: String = calculatedCoffee + attributedText

其中calculatedCoffee是一个Int转换为字符串和“attributedText”是小写的“g”与自定义字体,我试图创建。也许我做错了。任何帮助都是感激的!


当前回答

 let attrString = NSAttributedString (
            string: "title-title-title",
            attributes: [NSAttributedStringKey.foregroundColor: UIColor.black])

其他回答

细节

Swift 5.2, Xcode 11.4 (11E146)

解决方案

protocol AttributedStringComponent {
    var text: String { get }
    func getAttributes() -> [NSAttributedString.Key: Any]?
}

// MARK: String extensions

extension String: AttributedStringComponent {
    var text: String { self }
    func getAttributes() -> [NSAttributedString.Key: Any]? { return nil }
}

extension String {
    func toAttributed(with attributes: [NSAttributedString.Key: Any]?) -> NSAttributedString {
        .init(string: self, attributes: attributes)
    }
}

// MARK: NSAttributedString extensions

extension NSAttributedString: AttributedStringComponent {
    var text: String { string }

    func getAttributes() -> [Key: Any]? {
        if string.isEmpty { return nil }
        var range = NSRange(location: 0, length: string.count)
        return attributes(at: 0, effectiveRange: &range)
    }
}

extension NSAttributedString {

    convenience init?(from attributedStringComponents: [AttributedStringComponent],
                      defaultAttributes: [NSAttributedString.Key: Any],
                      joinedSeparator: String = " ") {
        switch attributedStringComponents.count {
        case 0: return nil
        default:
            var joinedString = ""
            typealias SttributedStringComponentDescriptor = ([NSAttributedString.Key: Any], NSRange)
            let sttributedStringComponents = attributedStringComponents.enumerated().flatMap { (index, component) -> [SttributedStringComponentDescriptor] in
                var components = [SttributedStringComponentDescriptor]()
                if index != 0 {
                    components.append((defaultAttributes,
                                       NSRange(location: joinedString.count, length: joinedSeparator.count)))
                    joinedString += joinedSeparator
                }
                components.append((component.getAttributes() ?? defaultAttributes,
                                   NSRange(location: joinedString.count, length: component.text.count)))
                joinedString += component.text
                return components
            }

            let attributedString = NSMutableAttributedString(string: joinedString)
            sttributedStringComponents.forEach { attributedString.addAttributes($0, range: $1) }
            self.init(attributedString: attributedString)
        }
    }
}

使用

let defaultAttributes = [
    .font: UIFont.systemFont(ofSize: 16, weight: .regular),
    .foregroundColor: UIColor.blue
] as [NSAttributedString.Key : Any]

let marketingAttributes = [
    .font: UIFont.systemFont(ofSize: 20.0, weight: .bold),
    .foregroundColor: UIColor.black
] as [NSAttributedString.Key : Any]

let attributedStringComponents = [
    "pay for",
    NSAttributedString(string: "one",
                       attributes: marketingAttributes),
    "and get",
    "three!\n".toAttributed(with: marketingAttributes),
    "Only today!".toAttributed(with: [
        .font: UIFont.systemFont(ofSize: 16.0, weight: .bold),
        .foregroundColor: UIColor.red
    ])
] as [AttributedStringComponent]
let attributedText = NSAttributedString(from: attributedStringComponents, defaultAttributes: defaultAttributes)

完整的示例

不要忘记在这里粘贴解决方案代码

import UIKit

class ViewController: UIViewController {

    private weak var label: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()
        let label = UILabel(frame: .init(x: 40, y: 40, width: 300, height: 80))
        label.numberOfLines = 2
        view.addSubview(label)
        self.label = label

        let defaultAttributes = [
            .font: UIFont.systemFont(ofSize: 16, weight: .regular),
            .foregroundColor: UIColor.blue
        ] as [NSAttributedString.Key : Any]

        let marketingAttributes = [
            .font: UIFont.systemFont(ofSize: 20.0, weight: .bold),
            .foregroundColor: UIColor.black
        ] as [NSAttributedString.Key : Any]

        let attributedStringComponents = [
            "pay for",
            NSAttributedString(string: "one",
                               attributes: marketingAttributes),
            "and get",
            "three!\n".toAttributed(with: marketingAttributes),
            "Only today!".toAttributed(with: [
                .font: UIFont.systemFont(ofSize: 16.0, weight: .bold),
                .foregroundColor: UIColor.red
            ])
        ] as [AttributedStringComponent]
        label.attributedText = NSAttributedString(from: attributedStringComponents, defaultAttributes: defaultAttributes)
        label.textAlignment = .center
    }
}

结果

Swift: xcode 6.1

    let font:UIFont? = UIFont(name: "Arial", size: 12.0)

    let attrString = NSAttributedString(
        string: titleData,
        attributes: NSDictionary(
            object: font!,
            forKey: NSFontAttributeName))

Xcode 6版本:

let attriString = NSAttributedString(string:"attriString", attributes:
[NSForegroundColorAttributeName: UIColor.lightGrayColor(), 
            NSFontAttributeName: AttriFont])

Xcode 9.3版本:

let attriString = NSAttributedString(string:"attriString", attributes:
[NSAttributedStringKey.foregroundColor: UIColor.lightGray, 
            NSAttributedStringKey.font: AttriFont])

Xcode 10, iOS 12, Swift 4:

let attriString = NSAttributedString(string:"attriString", attributes:
[NSAttributedString.Key.foregroundColor: UIColor.lightGray, 
            NSAttributedString.Key.font: AttriFont])

斯威夫特3、4、5所示

使用下面的代码为文本颜色,字体,背景颜色和下划线/下划线颜色

    let text = "swift is language"
    let attributes = [NSAttributedString.Key.foregroundColor: UIColor.red, NSAttributedString.Key.backgroundColor: UIColor.blue,NSAttributedString.Key.font: UIFont.systemFont(ofSize: 25.0),NSAttributedString.Key.underlineColor: UIColor.white,NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue] as [NSAttributedString.Key : Any]
        
    let textAttribute = NSAttributedString(string: text, attributes: attributes)
    swiftLabel1.attributedText = textAttribute

使用这个示例代码。这是满足您需求的非常短的代码。这对我很有用。

let attributes = [NSAttributedStringKey.font : UIFont(name: CustomFont.NAME_REGULAR.rawValue, size: CustomFontSize.SURVEY_FORM_LABEL_SIZE.rawValue)!]

let attributedString : NSAttributedString = NSAttributedString(string: messageString, attributes: attributes)