1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
/*
* This file is part of GNU Taler, ©2022-23 Taler Systems S.A.
* See LICENSE.md
*/
import SwiftUI
import Foundation
import UIKit
extension StringProtocol {
func trimURL() -> String {
if let url = URL(string: String(self)) {
if let host = url.host {
return host
}
}
return String(self)
}
func index<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> Index? {
range(of: string, options: options)?.lowerBound
}
func endIndex<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> Index? {
range(of: string, options: options)?.upperBound
}
func indices<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> [Index] {
ranges(of: string, options: options).map(\.lowerBound)
}
func ranges<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> [Range<Index>] {
var result: [Range<Index>] = []
var startIndex = self.startIndex
while startIndex < endIndex,
let range = self[startIndex...]
.range(of: string, options: options) {
result.append(range)
startIndex = range.lowerBound < range.upperBound ? range.upperBound :
index(range.lowerBound, offsetBy: 1, limitedBy: endIndex) ?? endIndex
}
return result
}
}
extension String {
func widthOfString(usingUIFont font: UIFont) -> CGFloat {
let fontAttributes = [NSAttributedString.Key.font: font]
let size = self.size(withAttributes: fontAttributes)
return size.width
}
func widthOfString(usingUIFont font: UIFont, _ sizeCategory: ContentSizeCategory) -> CGFloat {
let width = widthOfString(usingUIFont: font)
let correctForSize = correctForSize(sizeCategory)
return width * correctForSize
}
// This would be used like so:
// let uiFont = UIFont.systemFont(ofSize: 17, weight: .bold)
// let width = "SomeString".widthOfString(usingUIFont: uiFont)
///
fileprivate func correctForSize(_ sizeCategory: ContentSizeCategory) -> CGFloat {
let corrValue = switch sizeCategory {
case .extraSmall: 0.7
case .small: 0.8
case .medium: 0.9
// case .large: 1.0
case .extraLarge: 1.15
case .extraExtraLarge: 1.25
case .extraExtraExtraLarge: 1.33
case .accessibilityMedium: 1.52
case .accessibilityLarge: 1.8
case .accessibilityExtraLarge: 2.0
case .accessibilityExtraExtraLarge: 2.2
case .accessibilityExtraExtraExtraLarge: 2.5
default: 1.0
}
if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" {
// empirical values
return corrValue
} else {
// preview doesn't use ContentSizeCategory for widthOfString(usingUIFont)
// thus the empirical values are the square of what's really needed
return sqrt(corrValue)
}
}
}
|