//
|
// StringExtension.swift
|
// YYBase
|
//
|
// Created by alvin_y on 2020/3/7.
|
// Copyright © 2020 yangwang. All rights reserved.
|
//
|
|
import UIKit
|
import SwiftDate
|
import CommonCrypto
|
extension String{
|
//文字占用大小
|
func getStringRect(font:UIFont) -> CGRect {
|
let nsText: NSString = NSString( string: self )
|
let size:CGSize = CGSize(width: UIScreen.main.bounds.width, height: 0)
|
let options:NSStringDrawingOptions = NSStringDrawingOptions.usesFontLeading
|
let boundRec = nsText.boundingRect(with: size, options: options, attributes: [NSAttributedString.Key.font: font], context: nil)
|
return boundRec
|
}
|
|
//文字占用大小,给定宽度
|
func getStringRect(font:UIFont, width: CGFloat) -> CGRect {
|
let nsText: NSString = NSString( string: self )
|
let size:CGSize = CGSize(width: width, height: CGFloat(MAXFLOAT))
|
let options:NSStringDrawingOptions = NSStringDrawingOptions.usesFontLeading
|
let boundRec = nsText.boundingRect(with: size, options: options, attributes: [NSAttributedString.Key.font: font], context: nil)
|
return boundRec
|
}
|
}
|
|
extension String {
|
|
/// NSAttributedString工厂方法
|
///
|
/// - Parameters:
|
/// - color: 文字颜色
|
/// - fontSize: 字体大小
|
/// - Returns: 返回处理后的NSAttributedString类型
|
func makeAttributedString(color: UIColor, fontSize: CGFloat) -> NSAttributedString {
|
|
return NSAttributedString(string: self,
|
attributes: [NSAttributedString.Key.foregroundColor: color,
|
NSAttributedString.Key.font: UIFont.systemFont(ofSize: fontSize)])
|
}
|
|
/// NSAttributedString工厂方法
|
///
|
/// - Parameters:
|
/// - color: 文字颜色
|
/// - fontSize: 字体大小
|
/// - Returns: 返回处理后的NSAttributedString类型
|
func makeAttributedString(foregroundColor: UIColor, backgroundColor: UIColor, fontSize: CGFloat) -> NSAttributedString {
|
|
return NSAttributedString(string: self,
|
attributes: [NSAttributedString.Key.foregroundColor: foregroundColor,
|
NSAttributedString.Key.backgroundColor: backgroundColor,
|
NSAttributedString.Key.font: UIFont.systemFont(ofSize: fontSize)])
|
}
|
|
/// NSAttributedString工厂方法
|
///
|
/// - Parameters:
|
/// - color: 文字颜色
|
/// - font: 字体
|
/// - Returns: 返回处理后的NSAttributedString类型
|
func makeAttributedString(color: UIColor, font: UIFont) -> NSAttributedString {
|
|
return NSAttributedString(string: self,
|
attributes: [NSAttributedString.Key.foregroundColor: color,
|
NSAttributedString.Key.font: font])
|
}
|
|
}
|
|
// MARK: - General
|
extension String {
|
|
/// 手机号中间四位密文
|
///
|
/// - Returns: 返回加密文后的String类型,如果位数不够11位则返回不做处理
|
func securePhoneNumber() -> String {
|
guard self.count == 11 else { return self }
|
guard let range = Range(NSMakeRange(3, 4), in: self) else { return self }
|
|
let secureString = self.replacingCharacters(in: range, with: "****")
|
|
return secureString
|
}
|
}
|
|
|
// MARK: - String类型的拓展
|
public extension String{
|
|
/// 手机号正则
|
///
|
/// - Returns: true or false
|
func isPhoneNum()->Bool{
|
|
// 中国移动
|
// let isCM = isValidateByRegex("^1(34[0-8]|(3[5-9]|5[017-9]|8[2478])\\d)\\d{7}$")
|
// // 中国联通
|
// let isCU = isValidateByRegex("^1(3[0-2]|5[256]|8[356]|45|76)\\d{8}$")
|
// 中国电信
|
// let isCT = isValidateByRegex("^1((33|53|77|99||66||8[09])[0-9]|349)\\d{7}$")
|
// let isPhone = isValidateByRegex("^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(16[6])|(17[0,1,3,5-8])|(18[0-9])|(19[8,9]))\\d{8}$")
|
|
/*
|
if (mobileNum.length != 11)
|
{
|
return NO;
|
}
|
/**
|
* 手机号码:
|
* 13[0-9], 14[5,7], 15[0, 1, 2, 3, 5, 6, 7, 8, 9], 17[6, 7, 8], 18[0-9], 170[0-9]
|
* 移动号段: 134,135,136,137,138,139,150,151,152,157,158,159,182,183,184,187,188,147,178,1705
|
* 联通号段: 130,131,132,155,156,185,186,145,176,1709
|
* 电信号段: 133,153,180,181,189,177,1700
|
*/
|
NSString *MOBILE = @"^1((3[0-9]|4[57]|5[0-35-9]|7[0678]|8[0-9])\\d{8}$)";
|
/**
|
* 中国移动:China Mobile
|
* 134,135,136,137,138,139,150,151,152,157,158,159,182,183,184,187,188,147,178,1705
|
*/
|
NSString *CM = @"(^1(3[4-9]|4[7]|5[0-27-9]|7[8]|8[2-478])\\d{8}$)|(^1705\\d{7}$)";
|
/**
|
* 中国联通:China Unicom
|
* 130,131,132,155,156,185,186,145,176,1709
|
*/
|
NSString *CU = @"(^1(3[0-2]|4[5]|5[56]|7[6]|8[56])\\d{8}$)|(^1709\\d{7}$)";
|
/**
|
* 中国电信:China Telecom
|
* 133,153,180,181,189,177,1700
|
*/
|
NSString *CT = @"(^1(33|53|77|8[019])\\d{8}$)|(^1700\\d{7}$)";
|
|
|
NSPredicate *regextestmobile = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", MOBILE];
|
NSPredicate *regextestcm = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CM];
|
NSPredicate *regextestcu = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CU];
|
NSPredicate *regextestct = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CT];
|
|
if (([regextestmobile evaluateWithObject:mobileNum] == YES)
|
|| ([regextestcm evaluateWithObject:mobileNum] == YES)
|
|| ([regextestct evaluateWithObject:mobileNum] == YES)
|
|| ([regextestcu evaluateWithObject:mobileNum] == YES))
|
{
|
return YES;
|
}
|
else
|
{
|
return NO;
|
}
|
*/
|
if self.length != 11{
|
return false
|
}
|
// let isPhone = isValidateByRegex("^1((3[0-9]|4[57]|5[0-35-9]|7[0678]|8[0-9])\\d{8}$)")
|
let isPhone = isValidateByRegex("^1(([3-9])\\d{9}$)")
|
return isPhone
|
// return (isCM || isCU || isCT)
|
}
|
|
/// 身份证正则
|
///
|
/// - Returns: true or false
|
func isIDCardNum()->Bool{
|
return isValidateByRegex("^(\\d{14}|\\d{17})(\\d|[xX])$")
|
}
|
|
/// 手机号和座机正则
|
///
|
/// - Returns: true or false
|
func isPhoneNums()->Bool{
|
let isPhone = isValidateByRegex("^1(([3-9])\\d{9}$)")
|
let isFixedLine = isValidateByRegex("^0(10|2[0-5789]|\\d{3})\\d{7,8}$")
|
if isPhone == true || isFixedLine == true {
|
return true
|
}else{
|
return false
|
}
|
}
|
|
// 安全的手机号
|
func safePhone() -> String {
|
let s:NSString = self as NSString
|
if s.length > 7{
|
return s.replacingCharacters(in: NSMakeRange(3, 4), with: "****")
|
}else{
|
return s as String
|
}
|
|
}
|
|
// 安全的身份证号
|
func safeId() -> String {
|
let s:NSString = self as NSString
|
if s.length > 17{
|
return s.replacingCharacters(in: NSMakeRange(6, 8), with: "********")
|
}else{
|
return s as String
|
}
|
|
}
|
|
fileprivate func isValidateByRegex(_ regex:String) -> Bool {
|
return NSPredicate(format: "SELF MATCHES %@", regex).evaluate(with: self)
|
}
|
|
/// 银行卡号正则
|
///
|
/// - Returns: true or false
|
func isBankCarNum()->Bool{
|
|
for char in self {
|
if char == "_"{
|
return false
|
}
|
}
|
|
var result = ""
|
// - 1、创建规则
|
let pattern1 = "[0-9]{15,18}"
|
// let pattern1 = "^[a-zA-Z\\u4e00-\\u9fa5][a-zA-Z0-9\\u4e00-\\u9fa5]$"
|
// - 2、创建正则表达式对象
|
let regex1 = try! NSRegularExpression(pattern: pattern1, options: NSRegularExpression.Options.caseInsensitive)
|
// - 3、开始匹配
|
let res = regex1.matches(in: self, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, self.count))
|
// 输出结果
|
for checkingRes in res {
|
result = result + (self as NSString).substring(with: checkingRes.range)
|
}
|
if result == self{
|
return true
|
}else{
|
return false
|
}
|
|
}
|
|
/*
|
是否包含字母和数字之外的字符
|
*/
|
func containSpecialCharacters() -> Bool{
|
let nameCharacters = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789").inverted
|
let userNameRange = (self as NSString).rangeOfCharacter(from: nameCharacters)
|
if userNameRange.location != NSNotFound{
|
return true
|
}else{
|
return false
|
}
|
}
|
|
|
}
|
public extension String {
|
|
func encodeEscapesURL() -> String {
|
let str:NSString = self as NSString
|
let originalString = str as CFString
|
let charactersToBeEscaped = "+ " as CFString //":/?&=;+!@#$()',*" //转意符号
|
// let charactersToLeaveUnescaped = "[]./" as CFString //保留的符号
|
let result =
|
CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
|
originalString,
|
nil, //charactersToLeaveUnescaped,
|
charactersToBeEscaped,
|
CFStringConvertNSStringEncodingToEncoding(String.Encoding.utf8.rawValue)) as NSString
|
|
return result as String
|
}
|
}
|
public extension String {
|
|
/** 获取字符串长度 */
|
var length: Int {return self.count}
|
|
// 获取某个下标的字符
|
func character(at index: Int) -> Character {
|
return self[self.index(self.startIndex, offsetBy: index)]
|
}
|
|
// 从某个下标开始截取字符串
|
func substring(from index: Int) -> String {
|
return String(self[self.index(self.startIndex, offsetBy: index)...])
|
}
|
|
// 从开始截取到某个下标
|
func substring(to index: Int) -> String {
|
guard index <= self.count else {
|
return self
|
}
|
return String(self[..<self.index(self.startIndex, offsetBy: index)])
|
}
|
|
// 截取一个区域内的字符串
|
func substring(with range: Range<Int>) -> String {
|
let start = self.index(self.startIndex, offsetBy: range.lowerBound)
|
let end = self.index(self.startIndex, offsetBy: range.upperBound)
|
return String(self[start..<end])
|
}
|
|
// 转Int
|
func wy_toInt() -> Int {
|
return (self as NSString).integerValue
|
}
|
|
// 转Float
|
func wy_toFloat() -> CGFloat {
|
return CGFloat((self as NSString).floatValue)
|
}
|
|
// 转Double
|
func wy_toDouble() -> Double {
|
return (self as NSString).doubleValue
|
}
|
func wy_toLong() -> Int64 {
|
return (self as NSString).longLongValue
|
}
|
// 固定高计算文字的宽度
|
func width(_ font:CGFloat,height:CGFloat) -> CGFloat {
|
return (self as NSString).boundingRect(with: CGSize(width: UIScreen.main.bounds.width, height: height), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font:UIFont.systemFont(ofSize: font)], context: nil).size.width
|
}
|
|
// 固定高计算文字的宽度
|
func width(_ font: UIFont,height:CGFloat) -> CGFloat {
|
return (self as NSString).boundingRect(with: CGSize(width: UIScreen.main.bounds.width, height: height), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil).size.width
|
}
|
|
// 固定宽度计算文字的高度
|
func height(_ font:CGFloat,wight:CGFloat) -> CGFloat {
|
return (self as NSString).boundingRect(with: CGSize(width: wight, height: 2200), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font:UIFont.systemFont(ofSize: font)], context: nil).size.height
|
}
|
|
///适配Web,填充HTML的完整
|
var ld_warpHtml:String{
|
get{return "<html><head><meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0'><style>*{ width: 100%; margin: 0; padding: 0 3; box-sizing: border-box;} img{ width: 100%;}</style></head><body>\(self)</body></html>"}
|
}
|
|
// 汉字转拼音
|
func toPinYin() -> String {
|
let mutableString = NSMutableString(string: self)
|
CFStringTransform(mutableString, nil, kCFStringTransformToLatin, false)
|
CFStringTransform(mutableString, nil, kCFStringTransformStripDiacritics, false)
|
let string = String(mutableString)
|
return string.replacingOccurrences(of: " ", with: "")
|
}
|
|
// 返回大写拼音首字母, 如果不是拼音,返回#
|
func pinyinInitial(_ isHandelPolyphone:Bool = false) -> String {
|
if self.count == 0 {return "#"}
|
// 注意,这里一定要转换成可变字符串
|
let mutableString = NSMutableString.init(string: self)
|
// 将中文转换成带声调的拼音
|
CFStringTransform(mutableString as CFMutableString, nil, kCFStringTransformToLatin, false)
|
// 去掉声调
|
let pinyinString = mutableString.folding(options: String.CompareOptions.diacriticInsensitive, locale: NSLocale.current)
|
// 将拼音首字母装换成大写
|
let strPinYin = isHandelPolyphone ? polyphoneStringHandle(nameString: self, pinyinString: pinyinString).uppercased() : pinyinString.uppercased()
|
|
// 截取大写首字母
|
let firstString = strPinYin.substring(to: 1)
|
// 判断姓名首位是否为大写字母
|
let regexA = "^[A-Z]$"
|
let predA = NSPredicate.init(format: "SELF MATCHES %@", regexA)
|
return predA.evaluate(with: firstString) ? firstString : "#"
|
}
|
|
/// 多音字处理
|
private func polyphoneStringHandle(nameString:String, pinyinString:String) -> String {
|
if nameString.hasPrefix("长") {return "chang"}
|
if nameString.hasPrefix("沈") {return "shen"}
|
if nameString.hasPrefix("厦") {return "xia"}
|
if nameString.hasPrefix("地") {return "di"}
|
if nameString.hasPrefix("重") {return "chong"}
|
|
return pinyinString;
|
}
|
|
}
|
|
extension String{
|
|
//MARK:获得string内容高度
|
|
func stringHeightWith(fontSize:CGFloat,width:CGFloat)->CGFloat{
|
|
let font = UIFont.systemFont(ofSize: fontSize)
|
|
let size = CGSize(width: width, height: CGFloat(MAXFLOAT))
|
|
let paragraphStyle = NSMutableParagraphStyle()
|
|
paragraphStyle.lineBreakMode = .byWordWrapping;
|
|
let attributes = [NSAttributedString.Key.font:font,NSAttributedString.Key.paragraphStyle:paragraphStyle.copy()]
|
|
let text = self as NSString
|
|
let rect = text.boundingRect(with: size, options:.usesLineFragmentOrigin, attributes: attributes, context:nil)
|
|
return rect.size.height
|
|
}//funcstringHeightWith
|
|
}//extension end
|
|
extension String{
|
func byReplacing() -> String {
|
let str = self as NSString
|
let str1 = str.replacingOccurrences(of: "\n", with: "")
|
return str1
|
}
|
func bySpecialCharacters() -> String {
|
let str = self as NSString
|
let str1 = str.replacingOccurrences(of: "%", with: "%25").replacingOccurrences(of: "&", with: "%26").replacingOccurrences(of: "+", with: "%2B").replacingOccurrences(of: "=", with: "%2D").replacingOccurrences(of: "#", with: "%23")
|
return str1
|
}
|
func byReplacing(string:String) -> String {
|
let str = self as NSString
|
let str1 = str.replacingOccurrences(of: string, with: "")
|
return str1
|
}
|
func byReplacingContact() -> String {
|
let regular = try! NSRegularExpression(pattern: "[^\\d]", options: NSRegularExpression.Options.caseInsensitive)
|
let str1 = regular.stringByReplacingMatches(in: self, options: NSRegularExpression.MatchingOptions.init(rawValue: 0), range: NSRange.init(location: 0, length: self.length), withTemplate: "")
|
return str1
|
}
|
}
|
|
|
|
extension Double
|
{
|
|
/// 格式化时间
|
///
|
/// - Returns: yyyy-MM-dd
|
func toDate() -> String {
|
if self.string().length > 10{
|
return Date(timeIntervalSince1970: self / 1000).convertTo(region: .current).toFormat("yyyy-MM-dd")
|
}else{
|
return Date(timeIntervalSince1970: self).convertTo(region: .current).toFormat("yyyy-MM-dd")
|
}
|
|
}
|
/// 格式化时间
|
///
|
/// - Returns: yyyy-MM-dd
|
func toDate(toFormat: String) -> String {
|
if self.string().length > 10{
|
return Date(timeIntervalSince1970: self / 1000).convertTo(region: .current).toFormat(toFormat)
|
}else{
|
return Date(timeIntervalSince1970: self).convertTo(region: .current).toFormat(toFormat)
|
}
|
}
|
}
|
extension String
|
{
|
/// 格式化时间
|
///
|
/// - Returns: yyyy-MM-dd
|
func toDate(fromFormat: String,toFormat: String) -> String? {
|
let dateFormat = DateFormatter()
|
dateFormat.dateFormat = fromFormat
|
dateFormat.locale = .current
|
guard let date = dateFormat.date(from: self) else { return nil }
|
let fromzone = NSTimeZone.system
|
let frominterval = fromzone.secondsFromGMT(for: date)
|
let fromDate = date.addingTimeInterval(TimeInterval(frominterval))
|
return fromDate.toFormat(toFormat)
|
}
|
|
/// 格式化时间
|
///
|
/// - Returns: Date
|
func toDate(fromFormat: String) -> Date? {
|
let dateFormat = DateFormatter()
|
dateFormat.dateFormat = fromFormat
|
dateFormat.locale = .current
|
guard let date = dateFormat.date(from: self) else { return nil }
|
let fromzone = NSTimeZone.system
|
let frominterval = fromzone.secondsFromGMT(for: date)
|
let fromDate = date.addingTimeInterval(TimeInterval(frominterval))
|
return fromDate
|
}
|
}
|
|
|
extension String
|
{
|
func adaptWebViewForHtml() -> String {
|
let headHtml = NSMutableString.init(capacity: 0)
|
headHtml.append("<html>")
|
headHtml.append("<head>")
|
headHtml.append("<meta charset=\"utf-8\">")
|
headHtml.append("<meta id=\"viewport\" name=\"viewport\" content=\"width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=false\" />")
|
headHtml.append("<meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />")
|
headHtml.append("<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black\" />")
|
headHtml.append("<meta name=\"black\" name=\"apple-mobile-web-app-status-bar-style\" />")
|
headHtml.append("<script type='text/javascript'>" +
|
"window.onload = function(){\n" +
|
"var maxwidth=document.body.clientWidth;\n" +//屏幕宽度
|
"for(i=0;i <document.images.length;i++){\n" +
|
"var myimg = document.images[i];\n" +
|
"if(myimg.width > maxwidth){\n" +
|
"myimg.style.width = '100%';\n" +
|
"myimg.style.height = 'auto'\n;" +
|
"}\n" +
|
"}\n" +
|
"}\n" +
|
"</script>\n")
|
headHtml.append("<style>table{width:100%;}</style>")
|
headHtml.append("<title>webview</title>")
|
var bodyHtml = headHtml
|
bodyHtml = bodyHtml.appending(self as String) as! NSMutableString
|
return bodyHtml as String
|
}
|
}
|
|
|
extension String{
|
|
/// sha1加密
|
/// - Returns: String
|
func sha1() -> String {
|
let data = self.data(using: String.Encoding.utf8)!
|
var digest = [UInt8](repeating: 0, count:Int(CC_SHA1_DIGEST_LENGTH))
|
let newData = NSData.init(data: data)
|
CC_SHA1(newData.bytes, CC_LONG(data.count), &digest)
|
let output = NSMutableString(capacity: Int(CC_SHA1_DIGEST_LENGTH))
|
for byte in digest {output.appendFormat("%02x", byte)}
|
return output as String
|
}
|
|
func base64decode() -> String? {
|
let decodeData:Data? = Data.init(base64Encoded: self, options: Data.Base64DecodingOptions.init(rawValue: 0))
|
guard let utf8Data = decodeData else{
|
return nil
|
}
|
let decodedStr:String? = String.init(data: utf8Data, encoding: String.Encoding.utf8)
|
return decodedStr
|
}
|
|
func base64encode() -> String? {
|
let utf8str:Data? = self.data(using: String.Encoding.utf8)
|
guard let utf8Data = utf8str else{
|
return nil
|
}
|
let base64Encoded:String = utf8Data.base64EncodedString(options: Data.Base64EncodingOptions.init(rawValue: 0))
|
return base64Encoded
|
}
|
|
|
}
|
|
extension String {
|
var md5:String {
|
let utf8 = cString(using: .utf8)
|
var digest = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))
|
CC_MD5(utf8, CC_LONG(utf8!.count - 1), &digest)
|
return digest.reduce("") { $0 + String(format:"%02X", $1) }
|
}
|
}
|
|
|
enum CryptoAlgorithm {
|
case MD5, SHA1, SHA224, SHA256, SHA384, SHA512
|
|
var HMACAlgorithm: CCHmacAlgorithm {
|
var result: Int = 0
|
switch self {
|
case .MD5: result = kCCHmacAlgMD5
|
case .SHA1: result = kCCHmacAlgSHA1
|
case .SHA224: result = kCCHmacAlgSHA224
|
case .SHA256: result = kCCHmacAlgSHA256
|
case .SHA384: result = kCCHmacAlgSHA384
|
case .SHA512: result = kCCHmacAlgSHA512
|
}
|
return CCHmacAlgorithm(result)
|
}
|
|
var digestLength: Int {
|
var result: Int32 = 0
|
switch self {
|
case .MD5: result = CC_MD5_DIGEST_LENGTH
|
case .SHA1: result = CC_SHA1_DIGEST_LENGTH
|
case .SHA224: result = CC_SHA224_DIGEST_LENGTH
|
case .SHA256: result = CC_SHA256_DIGEST_LENGTH
|
case .SHA384: result = CC_SHA384_DIGEST_LENGTH
|
case .SHA512: result = CC_SHA512_DIGEST_LENGTH
|
}
|
return Int(result)
|
}
|
}
|
|
extension String {
|
func hmacBase64(algorithm: CryptoAlgorithm, key: String) -> String {
|
let str = self.cString(using: String.Encoding.utf8)
|
let strLen = Int(self.lengthOfBytes(using: String.Encoding.utf8))
|
let digestLen = algorithm.digestLength
|
let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)
|
let keyStr = key.cString(using: String.Encoding.utf8)
|
let keyLen = Int(key.lengthOfBytes(using: String.Encoding.utf8))
|
CCHmac(algorithm.HMACAlgorithm, keyStr!, keyLen, str!, strLen, result)
|
let hmacData:NSData = NSData(bytes: result, length: (Int(algorithm.digestLength)))
|
let hmacBase64 = hmacData.base64EncodedString(options: NSData.Base64EncodingOptions.lineLength76Characters)
|
result.deinitialize(count: digestLen)
|
return hmacBase64
|
}
|
|
func hmac(algorithm: CryptoAlgorithm, key: String) -> String {
|
let str = self.cString(using: String.Encoding.utf8)
|
let strLen = Int(self.lengthOfBytes(using: String.Encoding.utf8))
|
let digestLen = algorithm.digestLength
|
let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)
|
let keyStr = key.cString(using: String.Encoding.utf8)
|
let keyLen = Int(key.lengthOfBytes(using: String.Encoding.utf8))
|
CCHmac(algorithm.HMACAlgorithm, keyStr!, keyLen, str!, strLen, result)
|
let digest = stringFromResult(result: result, length: digestLen)
|
result.deinitialize(count: digestLen)
|
return digest
|
}
|
|
private func stringFromResult(result: UnsafeMutablePointer<CUnsignedChar>, length: Int) -> String {
|
let hash = NSMutableString()
|
for i in 0..<length {
|
hash.appendFormat("%02x", result[i])
|
}
|
return String(hash)
|
}
|
}
|
extension String {
|
///去掉字符串标签
|
func filterHTML() -> String?{
|
var content: String = self
|
let scanner = Scanner(string: self)
|
var text: NSString?
|
while !scanner.isAtEnd {
|
scanner.scanUpTo("<", into: nil)
|
scanner.scanUpTo(">", into: &text)
|
content = (content as NSString).replacingOccurrences(of: "\(text == nil ? "" : text!)>", with: "")
|
}
|
return content
|
}
|
|
/// 文本转换为富文本
|
func ld_setHtmlAttributedString(font: UIFont?, lineSpacing: CGFloat? = 10) -> NSMutableAttributedString {
|
var htmlString: NSMutableAttributedString? = nil
|
do {
|
if let data = self.replacingOccurrences(of: "\n", with: "<br/>").data(using: .utf8) {
|
htmlString = try NSMutableAttributedString(data: data, options: [
|
NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html,
|
NSAttributedString.DocumentReadingOptionKey.characterEncoding: NSNumber(value: String.Encoding.utf8.rawValue)], documentAttributes: nil)
|
let wrapHtmlString = NSMutableAttributedString(string: "\n")
|
// 判断尾部是否是换行符
|
if let weakHtmlString = htmlString, weakHtmlString.string.hasSuffix("\n") {
|
htmlString?.deleteCharacters(in: NSRange(location: weakHtmlString.length - wrapHtmlString.length, length: wrapHtmlString.length))
|
}
|
}
|
} catch {
|
}
|
|
// 设置富文本字的大小
|
if let font = font {
|
htmlString?.addAttributes([
|
NSAttributedString.Key.font: font], range: NSRange(location: 0, length: htmlString?.length ?? 0))
|
}
|
|
// 设置行间距
|
if let weakLineSpacing = lineSpacing {
|
let paragraphStyle = NSMutableParagraphStyle()
|
paragraphStyle.lineSpacing = weakLineSpacing
|
htmlString?.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: htmlString?.length ?? 0))
|
}
|
return htmlString ?? NSMutableAttributedString(string: self)
|
}
|
}
|