| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- //
- // String+Extension.swift
- // Lanu
- //
- // Created by OneeChan on 2025/11/6.
- //
- import Foundation
- import CommonCrypto
- extension String {
- init(key: String) {
- self = LNAppConfig.shared.languageBundle.localizedString(forKey: key, value: key, table: nil)
- }
-
- init(key: String, _ with: any CVarArg...) {
- let format = LNAppConfig.shared.languageBundle.localizedString(forKey: key, value: key, table: nil)
- self = String(format: format, with)
- }
- }
- extension String {
- /// 计算字符串的 MD5 哈希值(小写 32 位)
- var md5: String {
- // 将字符串转换为 UTF-8 数据
- guard let data = self.data(using: .utf8) else {
- return ""
- }
- return data.md5
- }
- }
- extension String {
- func toQRCode(size: CGFloat = 200, correctionLevel: String = "H") -> UIImage? {
- guard let contentData = data(using: .utf8) else {
- Log.e("字符串编码失败(仅支持 UTF-8)")
- return nil
- }
-
- // 2. 创建 CIQRCodeGenerator 滤镜
- guard let qrFilter = CIFilter(name: "CIQRCodeGenerator") else {
- Log.e("创建二维码滤镜失败")
- return nil
- }
-
- // 3. 设置滤镜参数:内容 + 容错率
- qrFilter.setValue(contentData, forKey: "inputMessage")
- // 容错率可选值:L(7%)、M(15%)、Q(25%)、H(30%),H 容错率最高
- qrFilter.setValue(correctionLevel, forKey: "inputCorrectionLevel")
-
- // 4. 获取 CIImage(原始二维码是小尺寸模糊图,需缩放)
- guard let ciImage = qrFilter.outputImage else {
- Log.e("生成 CIImage 失败")
- return nil
- }
-
- // 5. 缩放 CIImage 到指定尺寸(避免模糊)
- let scaleX = size / ciImage.extent.width
- let scaleY = size / ciImage.extent.height
- let scaledImage = ciImage.transformed(by: CGAffineTransform(scaleX: scaleX, y: scaleY))
-
- // 6. 转为 UIImage 并返回
- return UIImage(ciImage: scaledImage)
- }
- }
- extension String {
- // 修复 UUID 变化后的路径
- var fixedFilePath: String? {
- let currentAppRootPath = URL.rootDir.path
-
- // 解析原始路径的「子目录+文件名」(剔除沙盒根前缀+旧UUID)
- let sandboxPrefix = "/var/mobile/Containers/Data/Application/"
- guard hasPrefix(sandboxPrefix) else {
- return nil
- }
-
- // 截取沙盒前缀后的部分(旧UUID/子目录/文件名)
- let pathAfterPrefix = dropFirst(sandboxPrefix.count)
- // 拆分出「旧UUID」和「后续路径」(以第一个"/"分割)
- guard let firstSlashIndex = pathAfterPrefix.firstIndex(of: "/") else {
- return nil
- }
- let relativePath = pathAfterPrefix[firstSlashIndex...] // 如 "/Documents/Caches/123.jpeg"
-
- // 拼接当前应用根目录 + 原子孙目录
- let newPath = currentAppRootPath + relativePath
-
- return newPath
- }
- }
- // MARK: 拼音
- extension String {
- var classificationFirstLetter: String {
- // 1. 空字符串直接返回"#"
- guard !trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else {
- return "#"
- }
-
- // 2. 统一预处理:转为可变字符串(支持CFStringTransform修改)
- let mutableString = NSMutableString(string: self) as CFMutableString
-
- // 3. 步骤1:中文转带声调拼音(对英/印尼语无影响,可安全执行)
- CFStringTransform(mutableString, nil, kCFStringTransformMandarinLatin, false)
-
- // 4. 步骤2:去除所有重音符号(关键:处理印尼语重音+中文拼音声调)
- CFStringTransform(mutableString, nil, kCFStringTransformStripDiacritics, false)
-
- // 5. 步骤3:提取处理后的字符串首字符(忽略空白字符)
- let processedString = mutableString as String
- guard let firstChar = processedString
- .trimmingCharacters(in: .whitespacesAndNewlines)
- .first else {
- return "#"
- }
- let firstLetter = String(firstChar).uppercased()
-
- // 6. 步骤4:判断是否为A-Z字母,统一返回结果
- let isValidLetter = firstLetter.range(of: "^[A-Z]$", options: .regularExpression) != nil
- return isValidLetter ? firstLetter : "#"
- }
-
- var normalizedFullString: String {
- guard !isEmpty else { return "" }
- let mutableString = NSMutableString(string: self) as CFMutableString
- CFStringTransform(mutableString, nil, kCFStringTransformMandarinLatin, false)
- CFStringTransform(mutableString, nil, kCFStringTransformStripDiacritics, false)
- return (mutableString as String).uppercased()
- }
- }
- extension String {
- var extractSize: CGSize {
- let pattern = "(\\d+)x(\\d+)"
-
- guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else {
- return .zero
- }
-
- let range = NSRange(startIndex..., in: self)
- guard let match = regex.firstMatch(in: self, options: [], range: range) else {
- return .zero
- }
- let width = if let widthRange = Range(match.range(at: 1), in: self) {
- Int(String(self[widthRange]))
- } else {
- 0
- }
-
- let height = if let heightRange = Range(match.range(at: 2), in: self) {
- Int(String(self[heightRange]))
- } else {
- 0
- }
-
- return .init(width: width!, height: height!)
- }
- }
|