Skip to content

Commit fc06466

Browse files
committed
features development
1 parent ede7d83 commit fc06466

File tree

7 files changed

+269
-129
lines changed

7 files changed

+269
-129
lines changed

README.md

Lines changed: 48 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,44 +11,64 @@ Install with Cocoapods:
1111
pod 'appendAttributedString'
1212
```
1313

14+
Breaking changes in 1.2:
15+
16+
*Removed:*
17+
```swift
18+
AttributesBuilder().paragraph(style: _)
19+
```
20+
21+
*Added:*
22+
```swift
23+
AttributesBuilder().paragraphStyle(_)
24+
```
25+
1426
Here's an example:
1527

1628
```swift
17-
let textView = UITextView()
29+
let label = UILabel()
30+
label.numberOfLines = 0
31+
view.backgroundColor = .darkGray
32+
1833
let string = NSMutableAttributedString()
1934

20-
// dynamic fonts
21-
string.appendHeadline("Life can rise,\n")
35+
.appendHeadline("Life can rise,\n")
2236

23-
// call chaining
24-
.appendFootnote("it can fall.\n\n")
37+
// call chaining
38+
.appendFootnote("it can fall.\n\n")
2539

26-
// color, underline, strike through, superscript and others
27-
.append("But in the end\nit's just carried ", color: .white)
28-
.append("with the wind\n",
40+
// color, underline, strike through, superscript and others
41+
.append("But in the end\nit's just carried ", color: .white)
42+
.append("with the wind\n",
2943
color: .yellow,
3044
font: .dynamic(.systemFont(ofSize: 10)),
3145
baselineOffset: 5)
32-
.append("and one day everything you do will simply cease to be…\n\n",
33-
color: .green,
34-
underlineStyle: .styleDouble)
35-
.append("Like a child's ", color: .white)
36-
37-
// and even images
38-
.append(image: UIImage(named: "balloon")!,
39-
height: UIFontMetrics.default.scaledValue(for: 20)) // (the image will not auto-adjust its height)
40-
41-
// In specal cases use AttributesBuilder class for easier attributes set up
42-
.append("\n\nwhen it's lost, it's a tragic affair\n",
43-
withAttributes: AttributesBuilder()
44-
.color(.white)
45-
.shadow(offset: CGSize(width: 7, height: -5),
46-
blurRadius: 5, color: .yellow)
47-
.outline(width: -2, color: .red)
48-
.build())
49-
50-
.append("- but it is quickly forgotten.", withAttributes:
51-
AttributesBuilder().strikeThrough(.styleSingle, color: .white).build())
46+
.append("and one day everything you do will simply cease to be…\n\n",
47+
color: .green,
48+
underlineStyle: .double)
49+
.append("Like a child's ", color: .white)
50+
51+
// even images
52+
.append(image: UIImage(named: "balloon")!,
53+
// (the image will not auto-adjust its height)
54+
height: UIFontMetrics.default.scaledValue(for: 20))
55+
56+
.append("\n\n")
57+
58+
// In specal cases use AttributesBuilder class for easier attributes set up
59+
.append("when it's lost,\nit's a tragic affair\n",
60+
with: AttributesBuilder()
61+
.color(.white)
62+
.shadow(offset: CGSize(width: -7, height: 3),
63+
blurRadius: 5, color: .yellow)
64+
.outline(width: -2, color: .red)
65+
.lineSpacing(30)
66+
.align(.center))
67+
68+
.append("- but it is quickly forgotten.", with:
69+
AttributesBuilder()
70+
.strikeThrough(.double, color: .white)
71+
.align(.right))
5272

5373
textView.attributedText = string
5474
```

appendAttributedString/appendAttributedString.xcodeproj/project.pbxproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,23 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
718A261723A3E424000F7074 /* ParagraphStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 718A261623A3E424000F7074 /* ParagraphStyle.swift */; };
11+
718A261923A3E4BE000F7074 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 718A261823A3E4BE000F7074 /* StringExtension.swift */; };
1012
71B0E73E210C5C800058E7E0 /* appendAttributedString.h in Headers */ = {isa = PBXBuildFile; fileRef = 71B0E730210C5C800058E7E0 /* appendAttributedString.h */; settings = {ATTRIBUTES = (Public, ); }; };
1113
71B0E751210C5DAA0058E7E0 /* appendAttributedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71B0E74F210C5DAA0058E7E0 /* appendAttributedString.swift */; };
1214
71B0E752210C5DAA0058E7E0 /* AttributesBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71B0E750210C5DAA0058E7E0 /* AttributesBuilder.swift */; };
15+
71CC92F123A3F3D900D9102F /* DynamicFonts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71CC92F023A3F3D900D9102F /* DynamicFonts.swift */; };
1316
/* End PBXBuildFile section */
1417

1518
/* Begin PBXFileReference section */
19+
718A261623A3E424000F7074 /* ParagraphStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParagraphStyle.swift; sourceTree = "<group>"; };
20+
718A261823A3E4BE000F7074 /* StringExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtension.swift; sourceTree = "<group>"; };
1621
71B0E72D210C5C800058E7E0 /* appendAttributedString.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = appendAttributedString.framework; sourceTree = BUILT_PRODUCTS_DIR; };
1722
71B0E730210C5C800058E7E0 /* appendAttributedString.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = appendAttributedString.h; sourceTree = "<group>"; };
1823
71B0E731210C5C800058E7E0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
1924
71B0E74F210C5DAA0058E7E0 /* appendAttributedString.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = appendAttributedString.swift; sourceTree = "<group>"; };
2025
71B0E750210C5DAA0058E7E0 /* AttributesBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttributesBuilder.swift; sourceTree = "<group>"; };
26+
71CC92F023A3F3D900D9102F /* DynamicFonts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicFonts.swift; sourceTree = "<group>"; };
2127
/* End PBXFileReference section */
2228

2329
/* Begin PBXFrameworksBuildPhase section */
@@ -52,6 +58,9 @@
5258
children = (
5359
71B0E74F210C5DAA0058E7E0 /* appendAttributedString.swift */,
5460
71B0E750210C5DAA0058E7E0 /* AttributesBuilder.swift */,
61+
718A261623A3E424000F7074 /* ParagraphStyle.swift */,
62+
718A261823A3E4BE000F7074 /* StringExtension.swift */,
63+
71CC92F023A3F3D900D9102F /* DynamicFonts.swift */,
5564
71B0E730210C5C800058E7E0 /* appendAttributedString.h */,
5665
71B0E731210C5C800058E7E0 /* Info.plist */,
5766
);
@@ -139,7 +148,10 @@
139148
isa = PBXSourcesBuildPhase;
140149
buildActionMask = 2147483647;
141150
files = (
151+
71CC92F123A3F3D900D9102F /* DynamicFonts.swift in Sources */,
142152
71B0E752210C5DAA0058E7E0 /* AttributesBuilder.swift in Sources */,
153+
718A261723A3E424000F7074 /* ParagraphStyle.swift in Sources */,
154+
718A261923A3E4BE000F7074 /* StringExtension.swift in Sources */,
143155
71B0E751210C5DAA0058E7E0 /* appendAttributedString.swift in Sources */,
144156
);
145157
runOnlyForDeploymentPostprocessing = 0;

appendAttributedString/appendAttributedString/AttributesBuilder.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,27 @@
88

99
import UIKit
1010

11-
/// Helper class for creation of attributes for an NSAttributedString.
11+
/// Helper class for creation of attributes for an `NSAttributedString`.
1212
/// Use `build()` or `value` to get the result.
1313
public class AttributesBuilder {
1414

15-
/// The dictionary to use with NSAttributedString.
15+
/// The dictionary to use with `NSAttributedString`.
1616
public var value: [NSAttributedString.Key : Any]
1717

18-
/// Returns the dictionary to use with NSAttributedString.
18+
/// Returns the dictionary to use with `NSAttributedString`.
1919
public func build() -> [NSAttributedString.Key : Any] {
2020
return value
2121
}
2222

23-
/// Initialize a new clean instance of AttributesBuilder.
23+
/// Initialize a new clean instance of `AttributesBuilder`.
2424
public init(_ attributes: [NSAttributedString.Key : Any] = [:]) {
2525
value = attributes
2626
}
2727

2828
// MARK: - Methods
2929

3030
/// Returns the current font you've set with
31-
/// either dynamic(_:maximumPointSize:scaleAs:compatibleWith:) or font(_:)
31+
/// either `dynamic(_:maximumPointSize:scaleAs:compatibleWith:)` or `font(_:)`
3232
@available(iOS 11, *)
3333
public var font: UIFont? {
3434
return value[.font] as? UIFont
@@ -97,7 +97,7 @@ public class AttributesBuilder {
9797
}
9898

9999
/// Set paragraph style.
100-
public func paragraph(style: NSParagraphStyle?) -> Self {
100+
public func paragraphStyle(_ style: NSMutableParagraphStyle?) -> Self {
101101
value[.paragraphStyle] = style
102102
return self
103103
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
//
2+
// DynamicFonts.swift
3+
// https://github.com/ysoftware
4+
//
5+
// Created by Yaroslav Erohin on 13.12.2019.
6+
// Copyright © 2015 Yaroslav Erohin. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
public extension NSMutableAttributedString {
12+
13+
/// Adds a string with a dynamic font of style Title1.
14+
@available(iOS 9.0, *) @discardableResult
15+
func appendTitle1(_ string:String) -> Self {
16+
return append(string, font: .preferredFont(forTextStyle: .title1))
17+
}
18+
19+
/// Adds a string with a dynamic font of style Title2
20+
@available(iOS 9.0, *) @discardableResult
21+
func appendTitle2(_ string: String) -> Self {
22+
return append(string, font: .preferredFont(forTextStyle: .title2))
23+
}
24+
25+
/// Adds a string with a dynamic font of style Title3
26+
@available(iOS 9.0, *) @discardableResult
27+
func appendTitle3(_ string: String) -> Self {
28+
return append(string, font: .preferredFont(forTextStyle: .title3))
29+
}
30+
31+
/// Adds a string with a dynamic font of style Callout
32+
@available(iOS 9.0, *) @discardableResult
33+
func appendCallout(_ string: String) -> Self {
34+
return append(string, font: .preferredFont(forTextStyle: .callout))
35+
}
36+
37+
/// Adds a string with a dynamic font of style Subheadline
38+
@discardableResult
39+
func appendSubheadline(_ string: String) -> Self {
40+
return append(string, font: .preferredFont(forTextStyle: .subheadline))
41+
}
42+
43+
/// Adds a string with a dynamic font of style Caption1
44+
@discardableResult
45+
func appendCaption1(_ string: String) -> Self {
46+
return append(string, font: .preferredFont(forTextStyle: .caption1))
47+
}
48+
49+
/// Adds a string with a dynamic font of style Caption2
50+
@discardableResult
51+
func appendCaption2(_ string: String) -> Self {
52+
return append(string, font: .preferredFont(forTextStyle: .caption2))
53+
}
54+
55+
/// Adds a string with a dynamic font of style Headline
56+
@discardableResult
57+
func appendHeadline(_ string: String) -> Self {
58+
return append(string, font: .preferredFont(forTextStyle: .headline))
59+
}
60+
61+
/// Adds a string with a dynamic font of style Footnote
62+
@discardableResult
63+
func appendFootnote(_ string: String) -> Self {
64+
return append(string, font: .preferredFont(forTextStyle: .footnote))
65+
}
66+
67+
/// Adds a string with a dynamic font of style Body
68+
@discardableResult
69+
func appendBody(_ string: String) -> Self {
70+
return append(string, font: .preferredFont(forTextStyle: .body))
71+
}
72+
73+
/// Adds a string with a dynamic font of style Title1 or uses the fallback option if not available
74+
@discardableResult
75+
func appendTitle1(_ string: String,
76+
fallbackToStyle fallback: UIFont.TextStyle? = nil) -> Self {
77+
if #available(iOS 9.0, *) { return appendTitle1(string) }
78+
else { return append(string, style: fallback) }
79+
}
80+
81+
/// Adds a string with a dynamic font of style Title2 or uses the fallback option if not available
82+
@discardableResult
83+
func appendTitle2(_ string: String,
84+
fallbackToStyle fallback: UIFont.TextStyle? = nil) -> Self {
85+
if #available(iOS 9.0, *) { return appendTitle2(string) }
86+
else { return append(string, style: fallback) }
87+
}
88+
89+
/// Adds a string with a dynamic font of style Title3 or uses the fallback option if not available
90+
@discardableResult
91+
func appendTitle3(_ string: String,
92+
fallbackToStyle fallback: UIFont.TextStyle? = nil) -> Self {
93+
if #available(iOS 9.0, *) { return appendTitle3(string) }
94+
else { return append(string, style: fallback) }
95+
}
96+
97+
/// Adds a string with a dynamic font of style Callout
98+
@discardableResult
99+
func appendCallout(_ string: String,
100+
fallbackToStyle fallback: UIFont.TextStyle? = nil) -> Self {
101+
if #available(iOS 9.0, *) { return appendCallout(string) }
102+
else { return append(string, style: fallback) }
103+
}
104+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//
2+
// ParagraphStyle.swift
3+
// https://github.com/ysoftware
4+
//
5+
// Created by Ярослав Ерохин on 13.12.2019.
6+
// Copyright © 2017 Yaroslav Erohin. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
public extension AttributesBuilder {
12+
13+
private var paragraphStyle: NSMutableParagraphStyle {
14+
if value[.paragraphStyle] == nil {
15+
value[.paragraphStyle] = NSMutableParagraphStyle()
16+
}
17+
return value[.paragraphStyle]! as! NSMutableParagraphStyle
18+
}
19+
20+
/// Sets both min and max line heights for the attributed string's paragraph style.
21+
func lineHeight(_ lineHeight: CGFloat) -> Self {
22+
paragraphStyle.maximumLineHeight = lineHeight
23+
paragraphStyle.minimumLineHeight = lineHeight
24+
return self
25+
}
26+
27+
/// Sets both minimum line height for the attributed string's paragraph style.
28+
func minLineHeight(_ lineHeight: CGFloat) -> Self {
29+
paragraphStyle.minimumLineHeight = lineHeight
30+
return self
31+
}
32+
33+
/// Sets both maximum line height for the attributed string's paragraph style.
34+
func maxLineHeight(_ lineHeight: CGFloat) -> Self {
35+
paragraphStyle.maximumLineHeight = lineHeight
36+
return self
37+
}
38+
39+
/// Sets text alignment of the attributed string's paragraph style.
40+
func align(_ alignment: NSTextAlignment) -> Self {
41+
paragraphStyle.alignment = alignment
42+
return self
43+
}
44+
45+
/// Sets the mode that should be used to break lines in the attributed string's paragraph style.
46+
func lineBreak(_ mode: NSLineBreakMode) -> Self {
47+
paragraphStyle.lineBreakMode = mode
48+
return self
49+
}
50+
51+
/// Sets the distance in points between the bottom of one line fragment and the top of the next.
52+
/// This value is compensated to always be nonnegative.
53+
func lineSpacing(_ spacing: CGFloat) -> Self {
54+
paragraphStyle.lineSpacing = max(0, spacing)
55+
return self
56+
}
57+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//
2+
// StringExtension.swift
3+
// https://github.com/ysoftware
4+
//
5+
// Created by Ярослав Ерохин on 13.12.2019.
6+
// Copyright © 2017 Yaroslav Erohin. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
public extension String {
12+
13+
/// Creates a new instance of `NSMutableAttributedString`
14+
/// with given attributes from this `string`.
15+
func withAttributes(
16+
_ attributes: [NSAttributedString.Key : Any] = [:]) -> NSMutableAttributedString {
17+
18+
return NSMutableAttributedString().append(self, withAttributes: attributes)
19+
}
20+
21+
/// Creates a new instance of `NSMutableAttributedString` from this `string`
22+
/// with attributes passed in an `AttributesBuilder` instance.
23+
func withAttributes(
24+
_ builder: AttributesBuilder = .init()) -> NSMutableAttributedString {
25+
26+
return NSMutableAttributedString().append(self, with: builder)
27+
}
28+
}

0 commit comments

Comments
 (0)