Swift 字符串插值 String interpolation - 让NSAttributedString更简单

TTText

截屏2019-10-3010.26.26.png
Swift 5 string interpolation - NSAttributedString
使用TTText 让 NSAttributedString更方便,更简单

如何使用--上面图片样式的实现

let username = "Tema.Tian"

let str: TTText = """
Hello \(username, .color(.red)), isn't this \("cool", .color(.blue), .oblique, .underline(.purple, .single))?

\(wrap: """
\(" Pikachu! ", .font(.systemFont(ofSize: 36)), .color(.red), .bgColor(.yellow))
\(image: #imageLiteral(resourceName: "pikachu"))
""", .alignment(.center))

Go there to \("learn more about String Interpolation", .link("https://github.com/apple/swift-evolution/blob/master/proposals/0228-fix-expressiblebystringinterpolation.md"), .underline(.blue, .single))!
"""

label.attributedText = str.attributedString

源码

源码地址

public struct TTText {
  public let attributedString: NSAttributedString
}

extension TTText: ExpressibleByStringLiteral {
  public init(stringLiteral: String) {
    self.attributedString = NSAttributedString(string: stringLiteral)
  }
}

extension TTText: CustomStringConvertible {
  public var description: String {
    return String(describing: self.attributedString)
  }
}

extension TTText: ExpressibleByStringInterpolation {
  public init(stringInterpolation: StringInterpolation) {
    self.attributedString = NSAttributedString(attributedString: stringInterpolation.attributedString)
  }
  
  public struct StringInterpolation: StringInterpolationProtocol {
    var attributedString: NSMutableAttributedString
    
    public init(literalCapacity: Int, interpolationCount: Int) {
      self.attributedString = NSMutableAttributedString()
    }
    
    public func appendLiteral(_ literal: String) {
      let astr = NSAttributedString(string: literal)
      self.attributedString.append(astr)
    }
    
    public func appendInterpolation(_ string: String, attributes: [NSAttributedString.Key: Any]) {
      let astr = NSAttributedString(string: string, attributes: attributes)
      self.attributedString.append(astr)
    }
  }
}

extension TTText.StringInterpolation {
  public func appendInterpolation(_ string: String, _ style: TTText.Style) {
    let astr = NSAttributedString(string: string, attributes: style.attributes)
    self.attributedString.append(astr)
  }
}

extension TTText.StringInterpolation {
  public func appendInterpolation(_ string: String, _ style: TTText.Style...) {
    var attrs: [NSAttributedString.Key: Any] = [:]
    style.forEach { attrs.merge($0.attributes, uniquingKeysWith: {$1}) }
    let astr = NSAttributedString(string: string, attributes: attrs)
    self.attributedString.append(astr)
  }
}

extension TTText.StringInterpolation {
  public func appendInterpolation(image: UIImage, frame: CGRect = .zero) {
    let attachment = NSTextAttachment()
    let size = image.size
    if frame.equalTo(.zero) {
      attachment.bounds = CGRect(x: 0, y: 0, width: size.width, height: size.width)
    } else {
      attachment.bounds = frame
    }
    attachment.image = image
    self.attributedString.append(NSAttributedString(attachment: attachment))
  }
}

extension TTText.StringInterpolation {
  public func appendInterpolation(wrap string: TTText, _ style: TTText.Style...) {
    var attrs: [NSAttributedString.Key: Any] = [:]
    style.forEach { attrs.merge($0.attributes, uniquingKeysWith: {$1}) }
    let mas = NSMutableAttributedString(attributedString: string.attributedString)
    let fullRange = NSRange(mas.string.startIndex.. Style {
      return Style(attributes: [.font: font])
    }
    public static func color(_ color: UIColor) -> Style {
      return Style(attributes: [.foregroundColor: color])
    }
    public static func bgColor(_ color: UIColor) -> Style {
      return Style(attributes: [.backgroundColor: color])
    }
    public static func link(_ link: String) -> Style {
      return .link(URL(string: link)!)
    }
    public static func link(_ link: URL) -> Style {
      return Style(attributes: [.link: link])
    }
    public static func kern(_ kern: CGFloat) -> Style {
      return Style(attributes: [.kern: kern])
    }
    public static func paragraph(_ lineHeight: CGFloat, _ font: UIFont) -> Style {
      let paraStyle = NSMutableParagraphStyle()
      paraStyle.minimumLineHeight = lineHeight
      paraStyle.maximumLineHeight = lineHeight
      let baselineOffset = (lineHeight - font.lineHeight) / 4;
      return Style(attributes: [.paragraphStyle : paraStyle,
                                .baselineOffset : baselineOffset])
    }
    public static let oblique = Style(attributes: [.obliqueness: 0.1])
    public static func deleteline (_ color: UIColor, _ style: NSUnderlineStyle) -> Style {
      return Style(attributes: [
        .strikethroughStyle: style,
        .strikethroughColor: color
        ])
    }
    public static func underline(_ color: UIColor, _ style: NSUnderlineStyle) -> Style {
      return Style(attributes: [
        .underlineColor: color,
        .underlineStyle: style.rawValue
        ])
    }
    public static func stroke(_ color: UIColor, _ width: CGFloat) -> Style {
      return Style(attributes: [
        .strokeColor: color,
        .strokeWidth: width
        ])
    }
    public static func lineOffset(_ offset: CGFloat) -> Style {
      return Style(attributes: [
        .baselineOffset: offset
        ])
    }
    public static func expansion(_ expansion: CGFloat) -> Style {
      return Style(attributes: [
        .expansion: expansion
        ])
    }
    public static func alignment(_ alignment: NSTextAlignment) -> Style {
      let ps = NSMutableParagraphStyle()
      ps.alignment = alignment
      return Style(attributes: [.paragraphStyle: ps])
    }
  }
}

CocoaPods

使用CocoaPods是Cocoa项目的依赖项管理器。 您可以使用以下命令进行安装:

$ gem install cocoapods

要使用CocoaPods将TTText集成到Xcode项目中,请在Podfile中指定它:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '9.0'
use_frameworks!

target '' do
    pod 'TTText'
end

然后,运行以下命令:

pod install

Github Demo

你可能感兴趣的:(Swift 字符串插值 String interpolation - 让NSAttributedString更简单)