禁止转载,谢谢配合!!!
富文本属性链式编程实现:
原因 NSAttributedString 配置属性字典的时候太过麻烦,所以希望能简化这个过程,最终实现如下:
效果图 by SoaringHeart.jpg
🌰 🌰 :
let att0 = "Swift,".matt
.font(UIFont.systemFont(ofSize: 16))
.color(.systemBlue)
.underline(.single, .red)
.oblique(0.5)
.link("https://www.hackingwithswift.com")
// let att1 = NSAttributedString(string: " how do you like this?", attributes: nil)
let att1 = " how do you like this?".matt
.font(UIFont.systemFont(ofSize: 12))
.color(.systemGreen)
.strikethrough(.single, .lightRed)
// let att2 = NSAttributedString(string: ", YES?", attributes: nil)
let att2 = ", YES?".matt
.font(UIFont.systemFont(ofSize: 20))
.color(.systemOrange)
.oblique(-0.5)
let att3 = "666".matt
.color(.red)
.bgColor(.green)
.font(UIFont.systemFont(ofSize: 15))
.oblique(0.3)
textView.attributedText = (att0 + att1 + att2 + att3).matt
.font(UIFont.systemFont(ofSize: 30))
// .color(.systemPink)
// .bgColor(.lightGreen)
// .oblique(0.3)
Swift 实现
///属性链式编程实现
@objc public extension NSMutableAttributedString {
func font(_ font: UIFont) -> Self {
addAttributes([NSAttributedString.Key.font: font], range: NSMakeRange(0, self.length))
return self
}
func color(_ color: UIColor) -> Self {
addAttributes([NSAttributedString.Key.foregroundColor: color], range: NSMakeRange(0, self.length))
return self
}
func bgColor(_ color: UIColor) -> Self {
addAttributes([NSAttributedString.Key.backgroundColor: color], range: NSMakeRange(0, self.length))
return self
}
func link(_ value: String) -> Self {
return linkURL(URL(string: value)!)
}
func linkURL(_ value: URL) -> Self {
addAttributes([NSAttributedString.Key.link: value], range: NSMakeRange(0, self.length))
return self
}
//设置字体倾斜度,取值为float,正值右倾,负值左倾
func oblique(_ value: CGFloat = 0.1) -> Self {
addAttributes([NSAttributedString.Key.obliqueness: value], range: NSMakeRange(0, self.length))
return self
}
//字符间距
func kern(_ value: CGFloat) -> Self {
addAttributes([.kern: value], range: NSMakeRange(0, self.length))
return self
}
//设置字体的横向拉伸,取值为float,正值拉伸 ,负值压缩
func expansion(_ value: CGFloat) -> Self {
addAttributes([.expansion: value], range: NSMakeRange(0, self.length))
return self
}
//设置下划线
func underline(_ style: NSUnderlineStyle = .single, _ color: UIColor) -> Self {
addAttributes([
.underlineColor: color,
.underlineStyle: style.rawValue
], range: NSMakeRange(0, self.length))
return self
}
//设置删除线
func strikethrough(_ style: NSUnderlineStyle = .single, _ color: UIColor) -> Self {
addAttributes([
.strikethroughColor: color,
.strikethroughStyle: style.rawValue,
], range: NSMakeRange(0, self.length))
return self
}
//设置删除线
func stroke(_ color: UIColor, _ value: CGFloat = 0) -> Self {
addAttributes([
.strokeColor: color,
.strokeWidth: value,
], range: NSMakeRange(0, self.length))
return self
}
///设置基准位置 (正上负下)
func baseline(_ value: CGFloat) -> Self {
addAttributes([.baselineOffset: value], range: NSMakeRange(0, self.length))
return self
}
///设置段落
func paraStyle(_ alignment: NSTextAlignment,
lineSpacing: CGFloat = 0,
paragraphSpacingBefore: CGFloat = 0,
lineBreakMode: NSLineBreakMode = .byTruncatingTail) -> Self {
let style = NSMutableParagraphStyle()
style.alignment = alignment
style.lineBreakMode = lineBreakMode
style.lineSpacing = lineSpacing
style.paragraphSpacingBefore = paragraphSpacingBefore
addAttributes([.paragraphStyle: style], range: NSMakeRange(0, self.length))
return self
}
///设置段落
func paragraphStyle(_ style: NSMutableParagraphStyle) -> Self {
addAttributes([.paragraphStyle: style], range: NSMakeRange(0, self.length))
return self
}
}
public extension String {
/// -> NSMutableAttributedString
var matt: NSMutableAttributedString{
return NSMutableAttributedString(string: self)
}
}
@objc public extension NSAttributedString {
/// -> NSMutableAttributedString
var matt: NSMutableAttributedString{
return NSMutableAttributedString(attributedString: self)
}
}
///OC 版本(兼容Swift)
NSMutableAttributedString+Chain.h
//
// NSMutableAttributedString+Chain.h
// KTAttributedString
//
// Created by Bin Shang on 2020/12/20.
// Copyright © 2020 Shang. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSMutableAttributedString (Chain)
// addAttrs
@property(nonatomic, strong, readonly) NSMutableAttributedString *(^addAttrs)(NSDictionary<NSAttributedStringKey, id> *);
// ParagraphStyle
@property(nonatomic, strong, readonly) NSMutableAttributedString *(^paragraphStyle)(NSParagraphStyle *);
// Font
@property(nonatomic, strong, readonly) NSMutableAttributedString *(^font)(UIFont *);
@property(nonatomic, strong, readonly) NSMutableAttributedString *(^fontSize)(CGFloat);
// ForegroundColor
@property(nonatomic, strong, readonly) NSMutableAttributedString *(^color)(UIColor *);
// BackgroundColor
@property(nonatomic, strong, readonly) NSMutableAttributedString *(^bgColor)(UIColor *);
// Link
@property(nonatomic, strong, readonly) NSMutableAttributedString *(^link)(NSString *);
// Link
@property(nonatomic, strong, readonly) NSMutableAttributedString *(^linkURL)(NSURL *);
// Obliqueness
@property(nonatomic, strong, readonly) NSMutableAttributedString *(^oblique)(CGFloat);
// Kern
@property(nonatomic, strong, readonly) NSMutableAttributedString *(^kern)(CGFloat);
// Expansion
@property(nonatomic, strong, readonly) NSMutableAttributedString *(^expansion)(CGFloat);
// Ligature
@property(nonatomic, strong, readonly) NSMutableAttributedString *(^ligature)(NSUInteger);
// UnderlineStyle
@property(nonatomic, strong, readonly) NSMutableAttributedString *(^underline)(NSUnderlineStyle, UIColor *);
// StrikethroughStyle(负值填充效果,正值中空效果)
@property(nonatomic, strong, readonly) NSMutableAttributedString *(^strikethrough)(NSUnderlineStyle, UIColor *);
// Stroke
@property(nonatomic, strong, readonly) NSMutableAttributedString *(^stroke)(UIColor *, CGFloat);
// StrokeWidth
@property(nonatomic, strong, readonly) NSMutableAttributedString *(^baselineOffset)(CGFloat);
// Shadow
@property(nonatomic, strong, readonly) NSMutableAttributedString *(^shadow)(NSShadow *);
// TextEffect
@property(nonatomic, strong, readonly) NSMutableAttributedString *(^textEffect)(NSString *);
// Attachment
@property(nonatomic, strong, readonly) NSMutableAttributedString *(^attachment)(NSTextAttachment *);
@end
@interface NSString (Chain)
@property(nonatomic, strong, readonly) NSMutableAttributedString *matt;
@end
@interface NSAttributedString (Chain)
@property(nonatomic, strong, readonly) NSMutableAttributedString *matt;
@end
NS_ASSUME_NONNULL_END
NSMutableAttributedString+Chain.m
//
// NSMutableAttributedString+Chain.m
// SwiftTemplet
//
// Created by Bin Shang on 2020/12/20.
// Copyright © 2020 Shang. All rights reserved.
//
#import "NSMutableAttributedString+Chain.h"
@implementation NSMutableAttributedString (Chain)
- (NSMutableAttributedString * _Nonnull (^)(NSDictionary<NSAttributedStringKey, id> * _Nonnull))addAttrs{
return ^(NSDictionary<NSAttributedStringKey, id> * dic) {
[self addAttributes:dic range:NSMakeRange(0, self.length)];
return self;
};
}
- (NSMutableAttributedString * _Nonnull (^)(NSParagraphStyle * _Nonnull))paragraphStyle{
return ^(NSParagraphStyle *style) {
[self addAttributes:@{NSParagraphStyleAttributeName: style} range:NSMakeRange(0, self.length)];
return self;
};
}
- (NSMutableAttributedString *(^)(UIFont *))font {
return ^(UIFont *font) {
[self addAttributes:@{NSFontAttributeName: font} range:NSMakeRange(0, self.length)];
return self;
};
}
- (NSMutableAttributedString *(^)(CGFloat))fontSize {
return ^(CGFloat fontSize) {
[self addAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:fontSize]} range:NSMakeRange(0, self.length)];
return self;
};
}
- (NSMutableAttributedString *(^)(UIColor *))color {
return ^(UIColor *color) {
[self addAttributes:@{NSForegroundColorAttributeName: color} range:NSMakeRange(0, self.length)];
return self;
};
}
- (NSMutableAttributedString *(^)(UIColor *))bgColor {
return ^(UIColor *color) {
[self addAttributes:@{NSBackgroundColorAttributeName: color} range:NSMakeRange(0, self.length)];
return self;
};
}
- (NSMutableAttributedString *(^)(NSString *))link {
return ^(NSString *link) {
[self addAttributes:@{NSLinkAttributeName: link} range:NSMakeRange(0, self.length)];
return self;
};
}
- (NSMutableAttributedString *(^)(NSURL *))linkURL {
return ^(NSURL *link) {
[self addAttributes:@{NSLinkAttributeName: link} range:NSMakeRange(0, self.length)];
return self;
};
}
- (NSMutableAttributedString *(^)(CGFloat))oblique {
return ^(CGFloat value) {
[self addAttributes:@{NSObliquenessAttributeName: @(value)} range:NSMakeRange(0, self.length)];
return self;
};
}
- (NSMutableAttributedString *(^)(CGFloat))kern {
return ^(CGFloat kern) {
[self addAttributes:@{NSKernAttributeName: @(kern)} range:NSMakeRange(0, self.length)];
return self;
};
}
- (NSMutableAttributedString *(^)(CGFloat))expansion {
return ^(CGFloat value) {
[self addAttributes:@{NSExpansionAttributeName: @(value)} range:NSMakeRange(0, self.length)];
return self;
};
}
- (NSMutableAttributedString *(^)(NSUInteger))ligature {
return ^(NSUInteger ligature) {
[self addAttributes:@{NSLigatureAttributeName: @(ligature)} range:NSMakeRange(0, self.length)];
return self;
};
}
- (NSMutableAttributedString *(^)(NSUnderlineStyle, UIColor *))underline {
return ^(NSUnderlineStyle underline, UIColor *color) {
[self addAttributes:@{NSUnderlineStyleAttributeName: @(underline)} range:NSMakeRange(0, self.length)];
[self addAttributes:@{NSUnderlineColorAttributeName: color} range:NSMakeRange(0, self.length)];
return self;
};
}
- (NSMutableAttributedString *(^)(NSUnderlineStyle, UIColor *))strikethrough {
return ^(NSUnderlineStyle underline, UIColor *color) {
[self addAttributes:@{NSStrikethroughStyleAttributeName: @(underline)} range:NSMakeRange(0, self.length)];
[self addAttributes:@{NSStrikethroughColorAttributeName: color} range:NSMakeRange(0, self.length)];
return self;
};
}
- (NSMutableAttributedString * _Nonnull (^)(UIColor * _Nonnull, CGFloat))stroke{
return ^(UIColor *color, CGFloat value) {
[self addAttributes:@{NSStrokeColorAttributeName: color} range:NSMakeRange(0, self.length)];
[self addAttributes:@{NSStrokeWidthAttributeName: @(value)} range:NSMakeRange(0, self.length)];
return self;
};
}
- (NSMutableAttributedString *(^)(NSShadow *))shadow {
return ^(NSShadow *shadow) {
[self addAttributes:@{NSShadowAttributeName: shadow} range:NSMakeRange(0, self.length)];
return self;
};
}
- (NSMutableAttributedString *(^)(NSString *))textEffect {
return ^(NSString *textEffect) {
[self addAttributes:@{NSTextEffectAttributeName: textEffect} range:NSMakeRange(0, self.length)];
return self;
};
}
- (NSMutableAttributedString *(^)(NSTextAttachment *))attachment {
return ^(NSTextAttachment *attachment) {
[self addAttributes:@{NSAttachmentAttributeName: attachment} range:NSMakeRange(0, self.length)];
return self;
};
}
- (NSMutableAttributedString *(^)(CGFloat))baselineOffset {
return ^(CGFloat value) {
[self addAttributes:@{NSBaselineOffsetAttributeName: @(value)} range:NSMakeRange(0, self.length)];
return self;
};
}
@end
@implementation NSString (Chain)
- (NSMutableAttributedString *)matt {
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:self];
return attributedString;
}
@end
@implementation NSAttributedString (Chain)
- (NSMutableAttributedString *)matt {
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:self];
return attributedString;
}
@end
NSMutableParagraphStyle (Swift)
@objc public extension NSMutableParagraphStyle{
func lineSpacing(_ value: CGFloat) -> Self {
self.lineSpacing = value
return self
}
func paragraphSpacing(_ value: CGFloat) -> Self {
self.paragraphSpacing = value
return self
}
func alignment(_ value: NSTextAlignment) -> Self {
self.alignment = value
return self
}
func firstLineHeadIndent(_ value: CGFloat) -> Self {
self.firstLineHeadIndent = value
return self
}
func headIndent(_ value: CGFloat) -> Self {
self.headIndent = value
return self
}
func tailIndent(_ value: CGFloat) -> Self {
self.tailIndent = value
return self
}
func lineBreakMode(_ value: NSLineBreakMode) -> Self {
self.lineBreakMode = value
return self
}
func minimumLineHeight(_ value: CGFloat) -> Self {
self.minimumLineHeight = value
return self
}
func maximumLineHeight(_ value: CGFloat) -> Self {
self.maximumLineHeight = value
return self
}
func baseWritingDirection(_ value: NSWritingDirection) -> Self {
self.baseWritingDirection = value
return self
}
func lineHeightMultiple(_ value: CGFloat) -> Self {
self.lineHeightMultiple = value
return self
}
func paragraphSpacingBefore(_ value: CGFloat) -> Self {
self.paragraphSpacingBefore = value
return self
}
func hyphenationFactor(_ value: Float) -> Self {
self.hyphenationFactor = value
return self
}
func tabStops(_ value: [NSTextTab]) -> Self {
self.tabStops = value
return self
}
func defaultTabInterval(_ value: CGFloat) -> Self {
self.defaultTabInterval = value
return self
}
func allowsDefaultTighteningForTruncation(_ value: Bool) -> Self {
self.allowsDefaultTighteningForTruncation = value
return self
}
func lineBreakStrategy(_ value: NSParagraphStyle.LineBreakStrategy) -> Self {
self.lineBreakStrategy = value
return self
}
func addTabStopChain(_ value: NSTextTab) -> Self {
self.addTabStop(value)
return self
}
func removeTabStopChain(_ value: NSTextTab) -> Self {
self.removeTabStop(value)
return self
}
func setParagraphStyleChain(_ value: NSParagraphStyle) -> Self {
self.setParagraphStyle(value)
return self
}
}
NSMutableParagraphStyle (OC 版本兼容Swift)
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSMutableParagraphStyle (Chain)
@property(nonatomic, copy, readonly) NSMutableParagraphStyle *(^lineSpacingChain)(CGFloat);
@property(nonatomic, copy, readonly) NSMutableParagraphStyle *(^paragraphSpacingChain)(CGFloat);
@property(nonatomic, copy, readonly) NSMutableParagraphStyle *(^alignmentChain)(NSTextAlignment);
@property(nonatomic, copy, readonly) NSMutableParagraphStyle *(^firstLineHeadIndentChain)(CGFloat);
@property(nonatomic, copy, readonly) NSMutableParagraphStyle *(^headIndentChain)(CGFloat);
@property(nonatomic, copy, readonly) NSMutableParagraphStyle *(^tailIndentChain)(CGFloat);
@property(nonatomic, copy, readonly) NSMutableParagraphStyle *(^lineBreakModeChain)(NSLineBreakMode);
@property(nonatomic, copy, readonly) NSMutableParagraphStyle *(^minimumLineHeightChain)(CGFloat);
@property(nonatomic, copy, readonly) NSMutableParagraphStyle *(^maximumLineHeightChain)(CGFloat);
@property(nonatomic, copy, readonly) NSMutableParagraphStyle *(^baseWritingDirectionChain)(NSWritingDirection);
@property(nonatomic, copy, readonly) NSMutableParagraphStyle *(^lineHeightMultipleChain)(CGFloat);
@property(nonatomic, copy, readonly) NSMutableParagraphStyle *(^paragraphSpacingBeforeChain)(CGFloat);
@property(nonatomic, copy, readonly) NSMutableParagraphStyle *(^hyphenationFactorChain)(float);
@property(nonatomic, copy, readonly) NSMutableParagraphStyle *(^tabStopsChain)(NSArray<NSTextTab *> *) API_AVAILABLE(macos(10.0), ios(7.0));
@property(nonatomic, copy, readonly) NSMutableParagraphStyle *(^defaultTabIntervalChain)(CGFloat) API_AVAILABLE(macos(10.0), ios(7.0));
@property(nonatomic, copy, readonly) NSMutableParagraphStyle *(^allowsDefaultTighteningForTruncationChain)(BOOL) API_AVAILABLE(macos(10.11), ios(9.0));
@property(nonatomic, copy, readonly) NSMutableParagraphStyle *(^lineBreakStrategyChain)(NSLineBreakStrategy) API_AVAILABLE(macos(10.11), ios(9.0));
@property(nonatomic, copy, readonly) NSMutableParagraphStyle *(^addTabStopChain)(NSTextTab *) API_AVAILABLE(macos(10.11), ios(9.0));
@property(nonatomic, copy, readonly) NSMutableParagraphStyle *(^removeTabStopChain)(NSTextTab *) API_AVAILABLE(macos(10.11), ios(9.0));
@property(nonatomic, copy, readonly) NSMutableParagraphStyle *(^setParagraphStyleChain)(NSParagraphStyle *) API_AVAILABLE(macos(10.11), ios(9.0));
@end
NS_ASSUME_NONNULL_END
#import "NSMutableParagraphStyle+Chain.h"
@implementation NSMutableParagraphStyle (Chain)
- (NSMutableParagraphStyle * (^)(CGFloat))lineSpacingChain{
return ^(CGFloat value) {
self.lineSpacing = value;
return self;
};
}
- (NSMutableParagraphStyle * (^)(CGFloat))paragraphSpacingChain{
return ^(CGFloat value) {
self.paragraphSpacing = value;
return self;
};
}
- (NSMutableParagraphStyle * (^)(NSTextAlignment))alignmentChain{
return ^(NSTextAlignment value) {
self.alignment = value;
return self;
};
}
- (NSMutableParagraphStyle * (^)(CGFloat))firstLineHeadIndentChain{
return ^(CGFloat value) {
self.firstLineHeadIndent = value;
return self;
};
}
- (NSMutableParagraphStyle * (^)(CGFloat))headIndentChain{
return ^(CGFloat value) {
self.headIndent = value;
return self;
};
}
- (NSMutableParagraphStyle * (^)(CGFloat))tailIndentChain{
return ^(CGFloat value) {
self.tailIndent = value;
return self;
};
}
- (NSMutableParagraphStyle * (^)(NSLineBreakMode))lineBreakModeChain{
return ^(NSLineBreakMode value) {
self.lineBreakMode = value;
return self;
};
}
- (NSMutableParagraphStyle * (^)(CGFloat))minimumLineHeightChain{
return ^(CGFloat value) {
self.minimumLineHeight = value;
return self;
};
}
- (NSMutableParagraphStyle * (^)(CGFloat))maximumLineHeightChain{
return ^(CGFloat value) {
self.maximumLineHeight = value;
return self;
};
}
- (NSMutableParagraphStyle * (^)(NSWritingDirection))baseWritingDirectionChain{
return ^(NSWritingDirection value) {
self.baseWritingDirection = value;
return self;
};
}
- (NSMutableParagraphStyle * (^)(CGFloat))lineHeightMultipleChain{
return ^(CGFloat value) {
self.lineHeightMultiple = value;
return self;
};
}
- (NSMutableParagraphStyle * (^)(CGFloat))paragraphSpacingBeforeChain{
return ^(CGFloat value) {
self.paragraphSpacingBefore = value;
return self;
};
}
- (NSMutableParagraphStyle * (^)(float))hyphenationFactorChain{
return ^(float value) {
self.hyphenationFactor = value;
return self;
};
}
- (NSMutableParagraphStyle * (^)(NSArray<NSTextTab *> *))tabStopsChain{
return ^(NSArray<NSTextTab *> * value) {
self.tabStops = value;
return self;
};
}
- (NSMutableParagraphStyle * (^)(CGFloat))defaultTabIntervalChain{
return ^(CGFloat value) {
self.defaultTabInterval = value;
return self;
};
}
- (NSMutableParagraphStyle * (^)(BOOL))allowsDefaultTighteningForTruncationChain{
return ^(BOOL value) {
self.allowsDefaultTighteningForTruncation = value;
return self;
};
}
- (NSMutableParagraphStyle * (^)(NSLineBreakStrategy))lineBreakStrategyChain{
return ^(NSLineBreakStrategy value) {
self.lineBreakStrategy = value;
return self;
};
}
- (NSMutableParagraphStyle * (^)(NSTextTab *))addTabStopChain{
return ^(NSTextTab *value) {
[self addTabStop:value];
return self;
};
}
- (NSMutableParagraphStyle * (^)(NSTextTab *))removeTabStopChain{
return ^(NSTextTab *value) {
[self removeTabStop:value];
return self;
};
}
- (NSMutableParagraphStyle * (^)(NSParagraphStyle *))setParagraphStyleChain{
return ^(NSParagraphStyle *value) {
[self setParagraphStyle:value];
return self;
};
}
@end