123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- //
- // String+Ext.swift
- // PQSpeed
- //
- // Created by SanW on 2020/7/22.
- // Copyright © 2020 BytesFlow. All rights reserved.
- //
- import CommonCrypto
- import Foundation
- import MobileCoreServices
- public extension String {
- /// md5加密
- var md5: String {
- let str = cString(using: String.Encoding.utf8)
- let strLen = CUnsignedInt(lengthOfBytes(using: String.Encoding.utf8))
- let digestLen = Int(CC_MD5_DIGEST_LENGTH)
- let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)
- CC_MD5(str!, strLen, result)
- let hash = NSMutableString()
- for i in 0..<digestLen {
- hash.appendFormat("%02x", result[i])
- }
- result.deallocate()
- return hash as String
- }
- // 文件后缀名
- var pathExtension: String {
- return (self as NSString).pathExtension
- }
- func ga_widthForComment(font: UIFont, height: CGFloat = 15) -> 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)
- }
- //
- // public func ga_heightForComment(fontSize: CGFloat, width: CGFloat) -> CGFloat {
- // let font = UIFont.systemFont(ofSize: fontSize)
- // 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)
- // }
- //
- // public func ga_heightForComment(fontSize: CGFloat, width: CGFloat, maxHeight: CGFloat) -> CGFloat {
- // let font = UIFont.systemFont(ofSize: fontSize)
- // 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 enumerateSearchText(searchText: String?, complate: (_ idx: Int, _ range: NSRange) -> Void) {
- if searchText == nil || (searchText?.count ?? 0) <= 0 || !contains(searchText!) {
- return
- }
- let len: Int = searchText!.count
- var loc: Int = 0
- let subStrings: [String] = NSString(string: self).components(separatedBy: searchText!)
- for (idx, subText) in subStrings.enumerated() {
- loc = loc + subText.count
- let range = NSRange(location: loc, length: len)
- complate(idx, range)
- loc = loc + len
- if idx == subStrings.count - 2 {
- break
- }
- }
- }
- func attributedTextWithSearchText(searchText: String?, textColor: UIColor, textFont: UIFont, searchTextColor: UIColor, searchTextFont: UIFont) -> NSMutableAttributedString {
- let attbText = NSMutableAttributedString(string: self, attributes: [NSAttributedString.Key.font: textFont, NSAttributedString.Key.foregroundColor: textColor])
- if count <= 0 || searchText == nil || (searchText?.count ?? 0) <= 0 {
- return attbText
- }
- for tempStr in searchText! {
- enumerateSearchText(searchText: "\(tempStr)") { _, range in
- attbText.setAttributes([NSAttributedString.Key.font: searchTextFont, NSAttributedString.Key.foregroundColor: searchTextColor], range: range)
- }
- }
- return attbText
- }
- // 判断是否为空
- var isSpace: Bool {
- return allSatisfy { $0.isWhitespace }
- }
- /// 通过 文件路径/文件名/文件后缀 获取mimeType(文件媒体类型)
- /// - Parameter pathExtension: <#pathExtension description#>
- /// - Returns: <#description#>
- func mimeType() -> String {
- if let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (self as NSString).pathExtension as CFString, nil)?.takeRetainedValue() {
- if let mimetype = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?
- .takeRetainedValue()
- {
- return mimetype as String
- }
- }
- return "application/octet-stream"
- }
- // 将原始的url编码为合法的url
- func urlEncoded() -> String {
- let encodeUrlString = addingPercentEncoding(withAllowedCharacters:
- .urlQueryAllowed)
- return encodeUrlString ?? ""
- }
- // 将编码后的url转换回原始的url
- func urlDecoded() -> String {
- return removingPercentEncoding ?? ""
- }
- // 判断是否包含Emoji表情
- func isEmoji() -> Bool {
- let numbers = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
- guard !numbers.contains(self) else {
- return false
- }
- let tempEmoji: [Unicode.Scalar] = ["\u{26F8}", "\u{26F7}", "\u{263A}", "\u{2639}", "\u{2620}", "\u{270C}", "\u{261D}", "\u{0001F441}", "\u{0001F5E3}", "\u{0001F575}", "\u{0001F574}", "\u{26D1}", "\u{0001F576}", "\u{0001F577}", "\u{0001F54A}", "\u{0001F43F}", "\u{2618}", "\u{0001F32A}", "\u{2600}", "\u{0001F324}", "\u{0001F325}", "\u{2601}", "\u{0001F326}", "\u{0001F327}", "\u{26C8}", "\u{0001F329}", "\u{0001F328}", "\u{2744}", "\u{2603}", "\u{0001F32C}", "\u{2602}", "\u{0001F32B}", "\u{0001F336}", "\u{0001F37D}"]
- let scalars = unicodeScalars.map { $0.value }
- for element in scalars {
- if let scalar = Unicode.Scalar(element) {
- if #available(iOS 10.2, *) {
- if (scalar.properties.isEmoji && scalar.properties.isEmojiPresentation) || tempEmoji.contains(scalar) {
- return true
- } else {
- // BFLog(message: "是表情==\(element),\(scalar)")
- }
- }
- }
- }
- return false
- }
- internal var isContainsEmoji: Bool {
- for scalar in unicodeScalars {
- switch scalar.value {
- case 0x1F600...0x1F64F, // Emoticons
- 0x1F300...0x1F5FF, // Misc Symbols and Pictographs
- 0x1F680...0x1F6FF, // Transport and Map
- 0x2600...0x26FF, // Misc symbols
- 0x2700...0x27BF, // Dingbats
- 0xFE00...0xFE0F: // Variation Selectors
- return true
- default:
- continue
- }
- }
- return false
- }
- // 是否包含表情
- internal var containsEmoji: Bool {
- for scalar in unicodeScalars {
- switch scalar.value {
- case
- 0x00A0...0x00AF,
- 0x2030...0x204F,
- 0x2120...0x213F,
- 0x2190...0x21AF,
- 0x2310...0x329F,
- 0x1F000...0x1F9CF:
- return true
- default:
- continue
- }
- }
- return false
- }
- /**
- * 字母、数字、中文正则判断(不包括空格)
- *注意: 因为考虑到输入习惯,许多人习惯使用九宫格,这里在正常选择全键盘输入错误的时候,进行九宫格判断,九宫格对应的是下面➋➌➍➎➏➐➑➒的字符
- */
- internal static func isInputRuleNotBlank(str: String) -> Bool {
- let pattern = "^[a-zA-Z\\u4E00-\\u9FA5\\d]*$"
- let pred = NSPredicate(format: "SELF MATCHES %@", pattern)
- let isMatch = pred.evaluate(with: str)
- if !isMatch {
- let other = "➋➌➍➎➏➐➑➒"
- let len = str.count
- for i in 0..<len {
- let tmpStr = str as NSString
- let tmpOther = other as NSString
- let c = tmpStr.character(at: i)
- if !(isalpha(Int32(c)) > 0 || isalnum(Int32(c)) > 0 || (Int(c) == "_".hashValue) || (Int(c) == "-".hashValue) || (c >= 0x4E00 && c <= 0x9FA6) || (tmpOther.range(of: str).location != NSNotFound)) {
- return false
- }
- return true
- }
- }
- return isMatch
- }
- }
- public extension Optional where Wrapped == String {
- var isSpace: Bool {
- return self?.isSpace ?? true
- }
- }
|