String+Extension.swift 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. //
  2. // String+Extension.swift
  3. // QuickSearchLocation
  4. //
  5. // Created by Destiny on 2024/4/15.
  6. //
  7. import Foundation
  8. import UIKit
  9. import CommonCrypto
  10. // MARK: - 五、字符串UI的处理
  11. extension String {
  12. // MARK: 9.1、判断是否全是空白,包括空白字符和换行符号,长度为0返回true
  13. /// 判断是否全是空白,包括空白字符和换行符号,长度为0返回true
  14. public var isBlank: Bool {
  15. return self.trimmingCharacters(in: NSCharacterSet.whitespacesAndNewlines) == ""
  16. }
  17. // MARK: 5.1、对字符串(多行)指定出字体大小和最大的 Size,获取 (Size)
  18. /// 对字符串(多行)指定出字体大小和最大的 Size,获取展示的 Size
  19. /// - Parameters:
  20. /// - font: 字体大小
  21. /// - size: 字符串的最大宽和高
  22. /// - Returns: 按照 font 和 Size 的字符的Size
  23. public func rectSize(font: UIFont, size: CGSize) -> CGSize {
  24. let attributes = [NSAttributedString.Key.font: font]
  25. /**
  26. usesLineFragmentOrigin: 整个文本将以每行组成的矩形为单位计算整个文本的尺寸
  27. usesFontLeading:
  28. usesDeviceMetrics:
  29. @available(iOS 6.0, *)
  30. truncatesLastVisibleLine:
  31. */
  32. let option = NSStringDrawingOptions.usesLineFragmentOrigin
  33. let rect: CGRect = self.boundingRect(with: size, options: option, attributes: attributes, context: nil)
  34. return rect.size
  35. }
  36. // MARK: 5.2、对字符串(多行)指定字体及Size,获取 (高度)
  37. /// 对字符串指定字体及Size,获取 (高度)
  38. /// - Parameters:
  39. /// - font: 字体的大小
  40. /// - size: 字体的size
  41. /// - Returns: 返回对应字符串的高度
  42. public func rectHeight(font: UIFont, size: CGSize) -> CGFloat {
  43. return rectSize(font: font, size: size).height
  44. }
  45. // MARK: 5.3、对字符串(多行)指定字体及Size,获取 (宽度)
  46. /// 对字符串指定字体及Size,获取 (宽度)
  47. /// - Parameters:
  48. /// - font: 字体的大小
  49. /// - size: 字体的size
  50. /// - Returns: 返回对应字符串的宽度
  51. public func rectWidth(font: UIFont, size: CGSize) -> CGFloat {
  52. return rectSize(font: font, size: size).width
  53. }
  54. // MARK: 5.4、对字符串(单行)指定字体,获取 (Size)
  55. /// 对字符串(单行)指定字体,获取 (Size)
  56. /// - Parameter font: 字体的大小
  57. /// - Returns: 返回单行字符串的 size
  58. public func singleLineSize(font: UIFont) -> CGSize {
  59. let attrs = [NSAttributedString.Key.font: font]
  60. return self.size(withAttributes: attrs as [NSAttributedString.Key: Any])
  61. }
  62. // MARK: 5.5、对字符串(单行)指定字体,获取 (width)
  63. /// 对字符串(单行)指定字体,获取 (width)
  64. /// - Parameter font: 字体的大小
  65. /// - Returns: 返回单行字符串的 width
  66. public func singleLineWidth(font: UIFont) -> CGFloat {
  67. let attrs = [NSAttributedString.Key.font: font]
  68. return self.size(withAttributes: attrs as [NSAttributedString.Key: Any]).width
  69. }
  70. // MARK: 5.6、对字符串(单行)指定字体,获取 (Height)
  71. /// 对字符串(单行)指定字体,获取 (height)
  72. /// - Parameter font: 字体的大小
  73. /// - Returns: 返回单行字符串的 height
  74. public func singleLineHeight(font: UIFont) -> CGFloat {
  75. let attrs = [NSAttributedString.Key.font: font]
  76. return self.size(withAttributes: attrs as [NSAttributedString.Key: Any]).height
  77. }
  78. // MARK: 5.7、字符串通过 label 根据高度&字体 —> Size
  79. /// 字符串通过 label 根据高度&字体 ——> Size
  80. /// - Parameters:
  81. /// - height: 字符串最大的高度
  82. /// - font: 字体大小
  83. /// - Returns: 返回Size
  84. public func sizeAccording(width: CGFloat, height: CGFloat = CGFloat(MAXFLOAT), font: UIFont) -> CGSize {
  85. if self.isBlank {return CGSize(width: 0, height: 0)}
  86. let rect = CGRect(x: 0, y: 0, width: width, height: height)
  87. let label = UILabel(frame: rect).font(font).text(self).line(0)
  88. return label.sizeThatFits(rect.size)
  89. }
  90. // MARK: 5.8、字符串通过 label 根据高度&字体 —> Width
  91. /// 字符串通过 label 根据高度&字体 ——> Width
  92. /// - Parameters:
  93. /// - height: 字符串最大高度
  94. /// - font: 字体大小
  95. /// - Returns: 返回宽度大小
  96. public func widthAccording(width: CGFloat, height: CGFloat = CGFloat(MAXFLOAT), font: UIFont) -> CGFloat {
  97. if self.isBlank {return 0}
  98. let rect = CGRect(x: 0, y: 0, width: width, height: height)
  99. let label = UILabel(frame: rect).font(font).text(self).line(0)
  100. return label.sizeThatFits(rect.size).width
  101. }
  102. // MARK: 5.9、字符串通过 label 根据宽度&字体 —> height
  103. /// 字符串通过 label 根据宽度&字体 ——> height
  104. /// - Parameters:
  105. /// - width: 字符串最大宽度
  106. /// - font: 字体大小
  107. /// - Returns: 返回高度大小
  108. public func heightAccording(width: CGFloat, height: CGFloat = CGFloat(MAXFLOAT), font: UIFont) -> CGFloat {
  109. if self.isBlank {return 0}
  110. let rect = CGRect(x: 0, y: 0, width: width, height: height)
  111. let label = UILabel(frame: rect).font(font).text(self).line(0)
  112. return label.sizeThatFits(rect.size).height
  113. }
  114. // MARK: 5.10、字符串根据宽度 & 字体 & 行间距 —> Size
  115. /// 字符串根据宽度 & 字体 & 行间距 ——> Size
  116. /// - Parameters:
  117. /// - width: 字符串最大的宽度
  118. /// - heiht: 字符串最大的高度
  119. /// - font: 字体的大小
  120. /// - lineSpacing: 行间距
  121. /// - Returns: 返回对应的size
  122. public func sizeAccording(width: CGFloat, height: CGFloat = CGFloat(MAXFLOAT), font: UIFont, lineSpacing: CGFloat) -> CGSize {
  123. if self.isBlank {return CGSize(width: 0, height: 0)}
  124. let rect = CGRect(x: 0, y: 0, width: width, height: CGFloat(MAXFLOAT))
  125. let label = UILabel(frame: rect).font(font).text(self).line(0)
  126. let attrStr = NSMutableAttributedString(string: self)
  127. let paragraphStyle = NSMutableParagraphStyle()
  128. paragraphStyle.lineSpacing = lineSpacing
  129. attrStr.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: NSMakeRange(0, self.count))
  130. label.attributedText = attrStr
  131. return label.sizeThatFits(rect.size)
  132. }
  133. // MARK: 5.11、字符串根据宽度 & 字体 & 行间距 —> width
  134. /// 字符串根据宽度 & 字体 & 行间距 ——> width
  135. /// - Parameters:
  136. /// - width: 字符串最大的宽度
  137. /// - heiht: 字符串最大的高度
  138. /// - font: 字体的大小
  139. /// - lineSpacing: 行间距
  140. /// - Returns: 返回对应的 width
  141. public func widthAccording(width: CGFloat = CGFloat(MAXFLOAT), height: CGFloat, font: UIFont, lineSpacing: CGFloat) -> CGFloat {
  142. if self.isBlank {return 0}
  143. let rect = CGRect(x: 0, y: 0, width: width, height: height)
  144. let label = UILabel(frame: rect).font(font).text(self).line(0)
  145. let attrStr = NSMutableAttributedString(string: self)
  146. let paragraphStyle = NSMutableParagraphStyle()
  147. paragraphStyle.lineSpacing = lineSpacing
  148. attrStr.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: NSMakeRange(0, self.count))
  149. label.attributedText = attrStr
  150. return label.sizeThatFits(rect.size).width
  151. }
  152. // MARK: 5.12、字符串根据宽度 & 字体 & 行间距 —> height
  153. /// 字符串根据宽度 & 字体 & 行间距 ——> height
  154. /// - Parameters:
  155. /// - width: 字符串最大的宽度
  156. /// - heiht: 字符串最大的高度
  157. /// - font: 字体的大小
  158. /// - lineSpacing: 行间距
  159. /// - Returns: 返回对应的 height
  160. public func heightAccording(width: CGFloat, height: CGFloat = CGFloat(MAXFLOAT), font: UIFont, lineSpacing: CGFloat) -> CGFloat {
  161. if self.isBlank {return 0}
  162. let rect = CGRect(x: 0, y: 0, width: width, height: height)
  163. let label = UILabel(frame: rect).font(font).text(self).line(0)
  164. let attrStr = NSMutableAttributedString(string: self)
  165. let paragraphStyle = NSMutableParagraphStyle()
  166. paragraphStyle.lineSpacing = lineSpacing
  167. attrStr.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: NSMakeRange(0, self.count))
  168. label.attributedText = attrStr
  169. return label.sizeThatFits(rect.size).height
  170. }
  171. }
  172. // MARK: - Base64 编解码
  173. extension String {
  174. var decode: String {
  175. get {
  176. guard let decodeResult = self.base64String(encode: false) else { return "" }
  177. return decodeResult
  178. }
  179. }
  180. // Base64 编解码
  181. /// Base64 编解码
  182. /// - Parameter encode: true:编码 false:解码
  183. /// - Returns: 编解码结果
  184. func base64String(encode: Bool) -> String? {
  185. guard encode else {
  186. // 1.解码
  187. guard let decryptionData = Data(base64Encoded: self, options: .ignoreUnknownCharacters) else {
  188. return nil
  189. }
  190. return String(data: decryptionData, encoding: .utf8)
  191. }
  192. // 2.编码
  193. guard let codingData = self.data(using: .utf8) else {
  194. return nil
  195. }
  196. return codingData.base64EncodedString()
  197. }
  198. // func decode() -> String? {
  199. //
  200. // return self.base64String(encode: false)
  201. // }
  202. }
  203. extension String {
  204. /// 原生md5
  205. public var md5 : String {
  206. guard let data = data(using: .utf8) else {
  207. return self
  208. }
  209. var digest = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))
  210. #if swift(>=5.0)
  211. _ = data.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in
  212. return CC_MD5(bytes.baseAddress, CC_LONG(data.count), &digest)
  213. }
  214. #else
  215. _ = data.withUnsafeBytes { bytes in
  216. return CC_MD5(bytes, CC_LONG(data.count), &digest)
  217. }
  218. #endif
  219. return digest.map { String(format: "%02x", $0) }.joined()
  220. }
  221. }