字符串扩展

求字符串大小

extension String {
func getSize(_ font: UIFont) -> CGSize {
    let rect = NSString(string: self).boundingRect(with: CGSize(width: CGFloat(MAXFLOAT), height: CGFloat(MAXFLOAT)), options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)
    return rect.size
}

func getHeight(_ font: UIFont, _ width: CGFloat) -> CGFloat {
    let rect = NSString(string: self).boundingRect(with: CGSize(width: width, height: CGFloat(MAXFLOAT)), options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)
    return ceil(rect.height)
}

func getHeight(_ font: UIFont, _ width: CGFloat, _ maxHeight: CGFloat) -> CGFloat {
    let rect = NSString(string: self).boundingRect(with: CGSize(width: width, height: CGFloat(MAXFLOAT)), options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)
    return ceil(rect.height) > maxHeight ? maxHeight : ceil(rect.height)
}

func getWidth(_ font: UIFont, _ height: CGFloat) -> CGFloat {
    let rect = NSString(string: self).boundingRect(with: CGSize(width: CGFloat(MAXFLOAT), height: height), options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)
    return ceil(rect.width)
}

func getWidth(_ font: UIFont, _ height: CGFloat, _ maxWidth: CGFloat) -> CGFloat {
    let rect = NSString(string: self).boundingRect(with: CGSize(width: CGFloat(MAXFLOAT), height: height), options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)
    return ceil(rect.width) > maxWidth ? maxWidth : ceil(rect.width)
}
}

字符串解码、转换

extension String {
var unicodeStr: String {
    let tempStr1 = self.replacingOccurrences(of: "\\u", with: "\\U")
    let tempStr2 = tempStr1.replacingOccurrences(of: "\"", with: "\\\"")
    let tempStr3 = "\"".appending(tempStr2).appending("\"")
    let tempData = tempStr3.data(using: String.Encoding.utf8)
    var returnStr:String = ""
    do {
        returnStr = try PropertyListSerialization.propertyList(from: tempData!, options: [.mutableContainers], format: nil) as! String
    } catch {
        deprint(error)
    }
    return returnStr.replacingOccurrences(of: "\\r\\n", with: "\n")
}

func utf8Str() -> String {
    guard includeChinese() else {return self}
    return self.utf8HTMLStr()
}

func unicode() -> String {
    guard includeChinese() else {return self}
    
    
    return ""
}

func includeChinese() -> Bool {
    for (_, value) in self.enumerated() {
        if ("\u{4E00}" <= value  && value <= "\u{9FA5}") {
            return true
        }
    }
    
    return false
}

func toUTF8() -> String {
    var arr = [UInt8]()
    arr += self.utf8
    return String(bytes: arr, encoding: .utf8) ?? self
}

func GBK() -> String {
    let enc = CFStringConvertEncodingToNSStringEncoding(UInt32(CFStringEncodings.GB_18030_2000.rawValue))
    let str = String(data: data(using: .utf8)!, encoding: String.Encoding(rawValue: enc))
    return str ?? self
}

func utf8UrlStr() -> String {
    var set = CharacterSet()
    set.formUnion(CharacterSet.urlQueryAllowed)
    set.remove(charactersIn: "[].:/?&=;+!@#$()',*\"")
    return self.addingPercentEncoding(withAllowedCharacters: set) ?? self
}

func utf8HTMLStr() -> String {
    var result = ""
    
    for item  in self.utf16 {
        let str = String(format: "%04x", item)
        result.append("&#x" + str + ";")
    }
    
    return result
}
}

字符串截取

extension String {
/// 替换字符串最后一部分(例:AA>BB>CC,s 为:>,取:CC)
mutating func replaceLast(with str: String, s: String) {
    var arr = self.components(separatedBy: s)
    arr[arr.count - 1] = str
    self = arr.joined(separator: s)
}

/// 替换
mutating func replace(_ str: String, _ toStr: String) {
    var string = self
    
    if let range = string.range(of: str) {
        string.replaceSubrange(range, with: toStr)
    }
    
    self = string
}

mutating func removeLastSpace() {
    let str = self
    if str.last == " " {
        self = String(str.prefix(upTo: str.index(str.endIndex, offsetBy: -1)))
        self.removeLastSpace()
    }
}

static func isEmpty(_ string: String?) -> Bool {
    return string == nil || string == ""
}

func sub(_ start: Int, _ count: Int) -> String {
    let startIndex = self.index(self.startIndex, offsetBy: start)
    let endIndex =  self.index(self.startIndex, offsetBy: start + count)
    return String(self[startIndex..<endIndex])
}
}

字符串汉字处理

extension String { /// 列表排序
/// 判断字符串中是否有中文
func isIncludeChinese() -> Bool {
    for ch in self.unicodeScalars {
        if (0x4e00 < ch.value  && ch.value < 0x9fff) { return true } // 中文字符范围:0x4e00 ~ 0x9fff
    }
    return false
}

/// 获取大写首字母
func firstChar() -> String {
    guard self.count > 0 else {return ""}
    
    var firstString: String = ""
    
    //判断首字母是否为大写
    let regexA = "^[A-Z]$"
    let predA = NSPredicate(format: "SELF MATCHES %@", regexA)
    
    if isIncludeChinese() {
        let strPinYin = pinyinString()
        //截取大写首字母
        firstString = String(strPinYin.first!).uppercased()
    }else {
        firstString =  String(self.first!).uppercased()
    }
    
    return predA.evaluate(with: firstString) ? firstString : "#"
}

func pinyinString() -> String {
    //转变成可变字符串
    let mutableString = NSMutableString(string: self)
    
    //将中文转换成带声调的拼音
    CFStringTransform(mutableString as CFMutableString, nil, kCFStringTransformToLatin, false)
    
    //去掉声调
    let pinyinString = mutableString.folding(options: String.CompareOptions.diacriticInsensitive, locale: .current)
    
    //多音字
    let strPinYin = polyphoneStringHandle(nameString: self, pinyinString: pinyinString)
    
    return strPinYin
}

//多音字处理,根据需要添自行加
func polyphoneStringHandle(nameString: String, pinyinString: String) -> String {
    if nameString.hasPrefix("沈") {return "shen"}
    return pinyinString
}
}

字符串 Mac地址

extension String { // mac地址转换
func macType() -> String { /// 带 :的大写 Mac 地址
    if !self.contains(":") {
        var arr: [String] = []
        
        let j = 2
        let count = self.count / 2 + (self.count % 2 == 0 ? 0 : 1)
        for i in 0..<count {
            let str = self.sub(i * j, j)
            arr.append(str)
        }
        
        return arr.joined(separator: ":").uppercased()
    }
    return self.uppercased()
}

func tabType() -> String { /// 不带 :的十六进制地址
    return removeText(":").lowercased()
}

func removeText(_ text: String) -> String {
    if self.contains(text) {
        return self.replacingOccurrences(of: text, with: "")
    }
    return self
}
}

字符串进制转换

enum NumberType: Int {
case Octal = 8
case Hex = 16
case Decimal = 10
}

extension String {

// 整形的 utf8 编码范围
static let intRange = 48...57
// 小写 a~f 的 utf8 的编码范围
static let lowercaseRange = 97...102
// 大写 A~F 的 utf8 的编码范围
static let uppercasedRange = 65...70

// byte数组转字符串(Mac)
// bytes: byte数组
// capChar: 插入的字符
// range: 截取范围(元组)
// type: 进制
static func bytesToString(_ bytes: [UInt8],
                          _ capChar: String,
                          _ range: (Int, Int),
                          _ type: NumberType) -> String
{
    var result = ""
    let count = range.0 + range.1
    
    if bytes.count > count {
        for i in range.0..<count {
            var str = ""
            switch type {
            case .Octal:
                str = String(format: "%o", bytes[i])
            case .Hex:
                str = String(format: "%02X", bytes[i])
            case .Decimal:
                str = String(format: "%d", bytes[i])
            }
            
            result += str
            if i < (count - 1) {
                result += capChar
            }
        }
    }
    
    return result
}

// byte数组转日期字符串
// bytes: byte数组
// range: 截取范围(元组)
static func bytesTpDateString(_ bytes: [UInt8],
                              _ range: (Int, Int)) -> String {
    var result = ""
    let count = range.0 + range.1
    
    if bytes.count > count {
        for i in range.0..<count {
            result += String(format: "%02d", bytes[i])
        }
    }
    
    return result
}

// 字符串转data
// type: 传入的字符串的进制类型
func stringToData(_ type: NumberType) -> Data {
    var bytes: [UInt8] = []
    
    switch type {
    case .Decimal:
        bytes = self.decStringToBytes()
    case .Hex:
        bytes = self.hexStringToBytes()
    case .Octal:
        break
    }
    
    return Data(bytes)
}

// 十进制字符串转byte数组
func decStringToBytes() -> [UInt8] {
    var bytes: [UInt8] = []
    
    if self.count > 0, self.count % 2 == 0 {
        var sum = 0
        // 整形的 utf8 编码范围
        let intRange = 48...57
        for (index, c) in self.utf8CString.enumerated() {
            var intC = Int(c.byteSwapped)
            if intC == 0 {
                break
            } else if intRange.contains(intC) {
                intC -= 48
            } else {
                print("字符串格式不对,每个字符都需要在0~9内")
                break
            }
            sum = sum * 10 + intC

            if index % 2 != 0 {
                bytes.append(UInt8(sum))
                sum = 0
            }
        }
    }
    
    return bytes
}

// 十六进制字符串转byte数组
func hexStringToBytes() -> [UInt8] {
    var bytes: [UInt8] = []
    
    if self.count > 0, self.count % 2 == 0 {
        var sum = 0

        for (index, c) in self.utf8CString.enumerated() {
            var intC = Int(c.byteSwapped)
            if intC == 0 {
                break
            } else if String.intRange.contains(intC) {
                intC -= 48
            } else if String.lowercaseRange.contains(intC) {
                intC -= 87
            } else if String.uppercasedRange.contains(intC) {
                intC -= 55
            } else {
                print("字符串格式不对,每个字符都需要在0~9,a~f,A~F内")
                break
            }
            sum = sum * 16 + intC
            // 每两个十六进制字母代表8位,即一个字节
            if index % 2 != 0 {
                bytes.append(UInt8(sum))
                sum = 0
            }
        }
    }
    
    return bytes
}

// 单个十六进制转十进制
func hexToDec() -> Int {
    var result = -1
    
    if self.count > 0 {
        for c in self.utf8 {
            var i = Int(c.byteSwapped)
            if i  == 0 {
                result = 0
            }else if String.intRange.contains(i) {
                i -= 48
            }else if String.lowercaseRange.contains(i) {
                i -= 87
            }else if String.uppercasedRange.contains(i) {
                i -= 55
            }else {
                break
            }
            
            result = result * 16 + i
        }
    }
    
    return result
}

// 取子字符串数组
func substrings(_ subCount: Int) -> [String] {
    var result = [String]()
    
    if self.count > 0 {
        // 分组
        var count = self.count / subCount
        let remainder = self.count % subCount
        if remainder > 0 {
            count += 1
        }
        for i in 0..<count {
            let index = self.index(String.Index(utf16Offset: i * subCount, in: self), offsetBy: subCount)
            let subStr = String(self.prefix(upTo: index))
            result.append(subStr)
        }
    }
    
    return result
}

// 取字符数组
func characters() -> [Character] {
    var result = [Character]()
    
    if self.count > 0 {
        for char in self {
            result.append(char)
        }
    }
    
    return result
}
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,923评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,154评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,775评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,960评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,976评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,972评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,893评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,709评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,159评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,400评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,552评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,265评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,876评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,528评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,701评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,552评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,451评论 2 352

推荐阅读更多精彩内容