美文网首页
Swift:NSObject 扩展工具箱

Swift:NSObject 扩展工具箱

作者: 时光啊混蛋_97boy | 来源:发表于2022-01-10 10:07 被阅读0次

    原创:问题解决型文章
    创作不易,请珍惜,之后会持续更新,不断完善
    个人比较喜欢做笔记和写总结,毕竟好记性不如烂笔头哈哈,这些文章记录了我的IOS成长历程,希望能与大家一起进步
    温馨提示:由于简书不支持目录跳转,大家可通过command + F 输入目录标题后迅速寻找到你所需要的内容

    目录

    • 1、Array 的扩展
    • 2、Date 的扩展
    • 3、Dictionary 的扩展
    • 4、Int 的扩展
    • 5、NSMutableAttributedString 的扩展
    • 6、NSData 的扩展
    • 7、NSObject 的扩展
    • 8、Double 的扩展
    • 9、Float 的扩展
    • 10、CGFloat 的扩展
    • 11、String 的扩展
    • 12、Timer 的扩展

    1、Array 的扩展

    public extension Array
    
    arrayJsonString():将数组对象转换成json字符串
    func arrayJsonString() -> String? {
        if !JSONSerialization.isValidJSONObject(self) {
            return nil
        }
        if let data = try? JSONSerialization.data(withJSONObject: self, options: []),
           let string =  NSString(data: data, encoding: String.Encoding.utf8.rawValue){
            return string as String
        }
        return nil
    }
    
    eachItem(_ callback:((Int, Any)->Void)):遍历返回index和item
    openWhiteList.eachItem { (index, item) in
        
    }
    
    func eachItem(_ callback:((Int, Any)->Void)) {
        for (index,value) in self.enumerated() {
            callback(index,value)
        }
    }
    
    reduceArray(_ array:[Any], block:((Any) -> Bool)?):过滤数组
    /// block: 过滤器回调方法
    func reduceArray(_ array:[Any], block:((Any) -> Bool)?) -> [Any]? {
        var result = array
        if block != nil {
            for (_,item) in self.enumerated() {
                if (block!(item)) {
                    result.append(item)
                }
            }
        } else {
            result.append(contentsOf: self)
        }
        return result
    }
    
    firstRuleNumber(block: (Any) -> Bool):获取数组中符合规则的第一个数据
    func firstRuleNumber(block: (Any) -> Bool) -> Any? {
        for (_,item) in self.enumerated() {
            if (block(item)) {
                return item
            }
        }
        return nil
    }
    

    2、Date 的扩展

    public extension Date
    
    secondsPerDay:每天有多少秒
    var secondsPerDay: TimeInterval {
        get {
            return 24 * 60 * 60
        }
    }
    
    secondsPerHour:每小时有多少秒
    var secondsPerHour: TimeInterval {
        get {
            return 60 * 60
        }
    }
    
    secondsPerMinute:每分钟有多少秒
    var secondsPerMinute: TimeInterval {
        get {
            return 60
        }
    }
    
    yesterday:昨天
    var yesterday: Date {
        get {
            return self.addingTimeInterval(-secondsPerDay)
        }
    }
    
    tomorrow:明天
    var tomorrow: Date {
        get {
            return self.addingTimeInterval(secondsPerDay)
        }
    }
    
    lastWeek:上周
    var lastWeek: Date {
        get {
            return self.addingTimeInterval(-secondsPerDay * 7)
        }
    }
    
    lastThirtyDays:上个月
    var lastThirtyDays: Date {
        get {
            return self.addingTimeInterval(-secondsPerDay * 30)
        }
    }
    
    latest(_ day: Int) -> Date:获取间隔一定天数的日期(时间间隔可以是正数或负数)
    func latest(_ day: Int) -> Date {
        return self.addingTimeInterval(secondsPerDay * Double(day))
    }
    
    lastestMonth(_ month: Int) -> Date?:获取间隔一定月份的日期
    func lastestMonth(_ month: Int) -> Date? {
        var comps = DateComponents()
        comps.month = month
        if let calender = NSCalendar(calendarIdentifier: .gregorian) {
            let mDate = calender.date(byAdding: comps, to: self, options: NSCalendar.Options(rawValue: 0))
            return mDate
        }
        return nil
    }
    
    获取年月日时分秒
    var year: Int {
        return Calendar.current.dateComponents([.year], from: self).year ?? 0  // 默认0点
    }
    var month: Int {
        return Calendar.current.dateComponents([.month], from: self).month ?? 0  // 默认0点
    }
    var day: Int {
        return Calendar.current.dateComponents([.day], from: self).day ?? 0  // 默认0点
    }
    var hour: Int {
        return Calendar.current.dateComponents([.hour], from: self).hour ?? 0  // 默认0点
    }
    var minute: Int {
        return Calendar.current.dateComponents([.minute], from: self).minute ?? 0  // 默认0点
    }
    var second: Int {
        return Calendar.current.dateComponents([.second], from: self).second ?? 0  // 默认0点
    }
    
    timeIntervalDay:获取距离当前时间的天数

    self晚于当前时间24小时整数倍时,返回结果为负数,并且比实际时间长度绝对值小1。时间比较是以毫秒维度比较的,代码执行顺序会产生时间差异,这种情况建议手动处理。

    var timeIntervalDay: Int {
        return Calendar.current.dateComponents([.day], from: self, to: Date()).day ?? 0  // 默认0点
    }
    
    isBetweenFormHour(_ formHour:NSInteger,toHour:NSInteger):判断当前时间是否在两个时间段内
    func isBetweenFormHour(_ formHour:NSInteger,toHour:NSInteger) -> Bool {
        let dateFrom = self.getCustomDateWith(hour: formHour)
        let dateTo = self.getCustomDateWith(hour: toHour)
        
        let currentDate = self
        if (currentDate.compare(dateFrom) == .orderedDescending || currentDate.compare(dateFrom) == .orderedSame) && (currentDate.compare(dateTo) == .orderedAscending || currentDate.compare(dateTo) == .orderedSame){
            return true
        }
        return false
    }
    
    getCustomDateWith(hour:NSInteger) -> Date:根据小时获取自定义日期
    private func getCustomDateWith(hour:NSInteger) -> Date {
        let currentDate = self
        let currentCalendar = Calendar.init(identifier: .gregorian)
        var currentComps = DateComponents()
        currentComps = currentCalendar.dateComponents([Calendar.Component.year,Calendar.Component.month,Calendar.Component.day,Calendar.Component.weekday,Calendar.Component.hour,Calendar.Component.month,Calendar.Component.second], from: currentDate)
        
        var resultComps = DateComponents()
        resultComps.year = currentComps.year
        resultComps.month = currentComps.month
        resultComps.day = currentComps.day
        resultComps.hour = hour
        resultComps.minute = currentComps.minute
        
        let resultCalendar = Calendar.init(identifier: .gregorian)
        return resultCalendar.date(from: resultComps)!
    }
    
    standerTimeString():标准时间格式 yyyy-MM-dd
    func standerTimeString() ->String {
        let formate = DateFormatter()
        formate.dateFormat = "yyyy-MM-dd"
        formate.locale = NSLocale.current
        let str = formate.string(from: self)
        return str
    }
    
    standerTimeString():发表时间格式 MM-dd HH:mm
    func publishTimeString() -> String {
        let formate = DateFormatter()
        formate.dateFormat = "MM-dd HH:mm"
        formate.locale = NSLocale.current
        let str = formate.string(from: self)
        return str
    }
    
    standerTimeString():草稿时间格式 yyyy.MM.dd HH:mm
    func draftTimeString() -> String {
        let formate = DateFormatter()
        formate.dateFormat = "yyyy.MM.dd HH:mm"
        formate.locale = NSLocale.current
        let str = formate.string(from: self)
        return str
    }
    
    detailTimeString():详情时间格式 yyyy-MM-dd HH:mm
    func detailTimeString() -> String {
        let formate = DateFormatter()
        formate.dateFormat = "yyyy-MM-dd HH:mm"
        formate.locale = NSLocale.current
        let str = formate.string(from: self)
        return str
    }
    
    yyyymmdd():时间格式 yyyy.MM.dd
    func yyyymmdd() -> String {
        let formate = DateFormatter()
        formate.dateFormat = "yyyy.MM.dd"
        formate.locale = NSLocale.current
        let str = formate.string(from: self)
        return str
    }
    
    yearTimeString():只有年时间格式 yyyy
    func yearTimeString() -> String {
        let formate = DateFormatter()
        formate.dateFormat = "yyyy"
        formate.locale = NSLocale.current
        let str = formate.string(from: self)
        return str
    }
    
    yearTimeString():只有月时间格式 MM
    func monthTimeString() ->String {
        let formate = DateFormatter()
        formate.dateFormat = "MM"
        formate.locale = NSLocale.current
        let str = formate.string(from: self)
        return str
    }
    
    dayTimeString():只有天时间格式 dd
    func dayTimeString() ->String {
        let formate = DateFormatter()
        formate.dateFormat = "dd"
        formate.locale = NSLocale.current
        let str = formate.string(from: self)
        return str
    }
    
    hourTimeString():只有小时时间格式 HH
    func hourTimeString() -> String {
        let formate = DateFormatter()
        formate.dateFormat = "HH"
        formate.locale = NSLocale.current
        let str = formate.string(from: self)
        return str
    }
    
    minuteTimeString():只有分钟时间格式 mm
    func minuteTimeString() -> String {
        let formate = DateFormatter()
        formate.dateFormat = "mm"
        formate.locale = NSLocale.current
        let str = formate.string(from: self)
        return str
    }
    
    secondTimeString():只有秒时间格式 ss
    func secondTimeString() -> String {
        let formate = DateFormatter()
        formate.dateFormat = "ss"
        formate.locale = NSLocale.current
        let str = formate.string(from: self)
        return str
    }
    
    hhmmssString():时分秒时间格式 HH:mm:ss
    func hhmmssString() -> String {
        let formate = DateFormatter()
        formate.dateFormat = "HH:mm:ss"
        formate.locale = NSLocale.current
        let str = formate.string(from: self)
        return str
    }
    
    todayPublishTimeString():今天发布的时间格式 HH:mm
    func todayPublishTimeString() -> String {
        let formate = DateFormatter()
        formate.dateFormat = "HH:mm"
        formate.locale = NSLocale.current
        let str = formate.string(from: self)
        return str
    }
    
    liveStartTimeString():带中文的时间格式 MM月dd日 EEE HH:mm
    func liveStartTimeString() -> String {
        let formate = DateFormatter()
        formate.dateFormat = "MM月dd日 EEE HH:mm"
        formate.locale = NSLocale.current
        let str = formate.string(from: self)
        return str
    }
    
    weekTimeString():周时间格式 EEE
    func weekTimeString() -> String {
        let formate = DateFormatter()
        formate.dateFormat = "EEE"
        formate.locale = NSLocale.current
        let str = formate.string(from: self)
        return str
    }
    
    monthDayTimeString():月天时间格式 MM/dd
    func monthDayTimeString() -> String {
        let formate = DateFormatter()
        formate.dateFormat = "MM/dd"
        formate.locale = NSLocale.current
        let str = formate.string(from: self)
        return str
    }
    
    monthDayUnderLineTimeString():月天下划线时间格式 MM-dd
    func monthDayUnderLineTimeString() -> String {
        let formate = DateFormatter()
        formate.dateFormat = "MM-dd"
        formate.locale = NSLocale.current
        let str = formate.string(from: self)
        return str
    }
    
    yearAndMonthString():年月时间格式 YYYY年MM月
    func yearAndMonthString() -> String {
        let formatter = DateFormatter()
        formatter.dateFormat = "YYYY年MM月"
        formatter.locale = NSLocale.current
        let str = formatter.string(from: self)
        return str
    }
    
    weekString():星期时间格式 星期
    func weekString() -> String {
        let comp = Calendar.current.dateComponents([.weekday], from: self)
        let week = comp.weekday ?? 1
        var weekDayStr = ""
        switch (week) {
        case 1:
            weekDayStr = "星期日";
            break;
        case 2:
            weekDayStr = "星期一";
            break;
        case 3:
            weekDayStr = "星期二";
            break;
        case 4:
            weekDayStr = "星期三";
            break;
        case 5:
            weekDayStr = "星期四";
            break;
        case 6:
            weekDayStr = "星期五";
            break;
        case 7:
            weekDayStr = "星期六";
            break;
        default:
            weekDayStr = "";
            break;
        }
        return weekDayStr;
    }
    
    dateDisplayString():根据日期比较显示时间格式,从年月日开始比对,隐藏相同项
    func dateDisplayString() -> String {
        let nowComponents = Calendar.current.dateComponents([.year, .month, .day], from: Date())
        let selfComponents = Calendar.current.dateComponents([.year, .month, .day], from: self)
    
        if nowComponents.year == selfComponents.year &&
            nowComponents.month == selfComponents.month &&
            nowComponents.day == selfComponents.day {// 同天
            return todayPublishTimeString()
        }
    
        if nowComponents.year == selfComponents.year {// 同年
            return self.monthDayUnderLineTimeString()
        } else {// 不同年
            return self.yearTimeString()
        }
    }
    
    timeDisplayString():根据日期比较显示时间格式,细化到当天、昨天
    func timeDisplayString() -> String {
        if Calendar.current.isDateInToday(self) {// 当天: 时间段 + 00:00 - 23:59
            return todayPublishTimeString()
        } else if Calendar.current.isDateInYesterday(self) {// 昨天 时间段 + 00:00 - 23:59
            let time = todayPublishTimeString()
            return "昨天 \(time)"
        } else {
            let now = Date()
            let interval = now.timeIntervalSince(self)
            
            // 超过48小时: 星期几 + 时间段 + 00:00 - 23:59
            if interval > 3600 * 24 * 2 &&  interval < 3600 * 24 * 7  {
                let time = todayPublishTimeString()
                let week = weekString()
                return "\(week) \(time)"
            }
            
            // 超过一周: xxxx年xx月xx日 + 时间段 + 时间段 + 00:00 - 23:59       
            return detailTimeString()
        }
    }
    
    timeIntervalChangeToTimeString(timeInterval:TimeInterval, dateFormat:String?):时间戳转成字符串
    func timeIntervalChangeToTimeString(timeInterval:TimeInterval, dateFormat:String?) -> String {
        let date:NSDate = NSDate.init(timeIntervalSince1970: timeInterval)
        let formatter = DateFormatter.init()
        if dateFormat == nil {
            formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        } else {
            formatter.dateFormat = dateFormat
        }
        return formatter.string(from: date as Date)
    }
    
    intelligentDisplayString():NSDate的智能文本输出
    func intelligentDisplayString() -> String {
        let now = Date()
        let interval = now.timeIntervalSince(self)
        
        if interval < 60 {// 60秒之内显示刚刚
            return "刚刚"
        }
        if interval >= 60 && interval < 3600 {// 1小时之内显示n分钟前
            return "\(Int(interval / 60))分钟前"
        }
        if interval >= 3600 && interval < 3600 * 24 {// 1天之内显示n小时前
            return "\(Int(interval / 3600))小时前"
        }
    
        let nowComponents = Calendar.current.dateComponents([Calendar.Component.year], from: now)
        let selfComponents = Calendar.current.dateComponents([Calendar.Component.year], from: self)
        if nowComponents.year == selfComponents.year {// 本年度显示MM-dd
            return monthDayUnderLineTimeString()
        } else {// 非本年显示YYYY-MM-dd
            return standerTimeString()
        }
    }
    
    getDate(dateStr: String, format: String):自定义日期格式
    static func getDate(dateStr: String, format: String) -> Date? {
        let dateFormatter = DateFormatter()
        dateFormatter.locale = Locale.current
        dateFormatter.timeZone = TimeZone.current
        dateFormatter.dateFormat = format
        let date = dateFormatter.date(from: dateStr)
        return date
    }
    
    format(to format: String):自定义日期格式
    func format(to format: String) -> String {
        let formatter = DateFormatter()
        formatter.dateFormat = format
        return formatter.string(from: self)
    }
    
    timestamp: TimeInterval:获取时间戳
    var timestamp: TimeInterval {
        return self.timeIntervalSince1970
    }
    
    isSameDay (date1: Date?, date2: Date?):是否同一天
    static func isSameDay (date1: Date?, date2: Date?) -> Bool {
        guard date1 != nil else {return false}
        guard date2 != nil else {return false}
        
        let calendar = Calendar.current
        let comp1 = calendar.dateComponents([.year, .month, .day], from: date1!)
        let comp2 = calendar.dateComponents([.year, .month, .day], from: date2!)
        return comp1.year == comp2.year && comp1.month == comp2.month && comp1.day == comp2.day
    }
    

    3、Dictionary 的扩展

    public extension Dictionary
    
    jsonDictionaryString():字典转JSON
    func jsonDictionaryString() -> String? {
        if !JSONSerialization.isValidJSONObject(self) {
            return nil
        }
        if let data = try? JSONSerialization.data(withJSONObject: self, options: []),
           let string =  NSString(data: data, encoding: String.Encoding.utf8.rawValue){
            return string as String
        }
        return nil
    }
    
    has(key: Key):判断是否包含key
    func has(key: Key) -> Bool {
        return index(forKey: key) != nil
    }
    
    removeAll(keys: [Key])
    mutating func removeAll(keys: [Key]) {
        keys.forEach({ removeValue(forKey: $0)})
    }
    
    mergeWith(_ newDic:[Key:Value]):合并字典,返回新的字典,相同key值会被newDic中的value覆盖
    func mergeWith(_ newDic:[Key:Value]) -> [Key:Value] {
        var result = self
        newDic.forEach { result[$0] = $1 }
        return result
    }
    
    appendWith(_ newDic:[Key:Value]):添加新字典到当前字典,不返回新字典
    mutating func appendWith(_ newDic:[Key:Value]) {
        newDic.forEach { self[$0] = $1 }
    }
    

    4、Int 的扩展

    Int64
    public extension Int64
    
    var number:Int64 = 8008
    var str =  number.ml_numToString()// 8k
    number = 8808
    str = number.ml_numToString()// 8.8k
    
    numToString():数字显示格式
    func numToString() -> String{
        let num = Double(self)
        if num < 0.0 {
            return String(0)
        }
        switch num {
        case 0...999:
            let numString = String(format: "%.0f", num)
            return "\(numString)"
        case 1000...9999:
            var numString = String(format: "%.1f", num/1000)
            if numString.hasSuffix(".0") {
                numString = numString[0..<Int(numString.ml_length - 2)]
            }
            return "\(numString)k"
        default:
            var numString = String(format: "%.1f", num/10_000)
            if numString.hasSuffix(".0") {
                numString = numString[0..<Int(numString.ml_length - 2)]
            }
            return "\(numString)w"
        }
    }
    
    Int32
    public extension Int32
    
    numToString():数字显示格式
    func numToString() -> String {
        let int64 = Int64(self)
        return int64.numToString()
    }
    
    Int
    public extension Int
    
    numToString():数字显示格式
    func numToString() -> String {
        let int64 = Int64(self)
        return int64.numToString()
    }
    
    secondToRecordString():时间显示格式
    var time = 99.ml_secondToRecordString()// 00:01:39
    time = 9.ml_secondToRecordString()// 00:00:09
    
    func secondToRecordString() -> String {
        var tmphh = "\(self / 3600)" as NSString
        if tmphh.length == 1 {
            tmphh = NSString(format: "0%@", tmphh)
        }
        var tmpmm = "\((self/60)%60)" as NSString
        if tmpmm.length == 1 {
            tmpmm = NSString(format: "0%@", tmpmm)
        }
        var tmpss = "\(self%60)" as NSString
        if tmpss.length == 1 {
            tmpss = NSString(format: "0%@", tmpss)
        }
        return NSString(format: "%@:%@:%@",tmphh,tmpmm,tmpss) as String
    }
    
    random:得到一个Int随机数,0到Int类型最大值
    public static var random: Int {
        get {
            return Int.random(withMax: Int.max)
        }
    }
    
    random(withMax n: Int):获取一个0到n-1的Int随机数
    public static func random(withMax n: Int) -> Int {
        return Int(arc4random_uniform(UInt32(n)))
    }
    
    random(lower min: Int, upper max: Int) -> Int:获取一个min到max的Int随机数
    public static func random(lower min: Int, upper max: Int) -> Int {
        return Int.random(withMax: max - min + 1) + min
    }
    

    5、NSMutableAttributedString 的扩展

    public  extension NSMutableAttributedString
    
    attributenStringColor:选中字体颜色变红
    //text: 所有字符串
    //selectedText: 需要变颜色的字符串
    //allColor: 字符串本来颜色
    //selectedColor: 选中字符串颜色
    //font: 字符串字体大小
    //selectedFont: 选中字符串字体大小
    static func attributenStringColor(text:String,
                                 selectedText: String,
                                 allColor: UIColor,
                                 selectedColor: UIColor,
                                 font: UIFont,
                                 selectedFont:UIFont)->NSMutableAttributedString{
        var rangeArray: [NSRange] = [NSRange]()
        var lastLength: Int = 0
        let attStr = NSMutableAttributedString.init(string: text, attributes: [NSAttributedString.Key.font :  font,NSAttributedString.Key.foregroundColor:allColor])
        var text = text as NSString
        
        while text.contains(selectedText) {
            let rang: NSRange =  text.range(of: selectedText)
            let rang2 = NSMakeRange(rang.location + lastLength, rang.length)
            rangeArray.append(rang2)
            lastLength += (rang.length + rang.location )
            text = text.substring(from: rang.length + rang.location) as NSString
        }
        
        for range1 in rangeArray {
            attStr.setAttributes([NSAttributedString.Key.foregroundColor:selectedColor,NSMutableAttributedString.Key.font: selectedFont], range: range1)
        }
        
        return attStr
    }
    
    attributenStringColor:选中字体颜色变红
    //text: 整体字符串
    //lineSpace: 行间距
    //font: 字图
    static func lineSpace(text: String,lineSpace: CGFloat,font: CGFloat)->NSMutableAttributedString {
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineSpacing = lineSpace
        let attStr = NSMutableAttributedString.init(string: text, attributes: [NSAttributedString.Key.font : UIFont.systemFont(ofSize: font)])
        attStr.addAttributes([NSAttributedString.Key.paragraphStyle : paragraphStyle], range: NSMakeRange(0, text.count))
        return attStr
    }
    

    6、NSData 的扩展

    public  extension NSData
    
    writeImageDataTofolder:将数据写入到本地文件
    enum FolderType: String {
        case pickImage = "pickImage"
    }
    
    func writeTofolder(_ folderType: FolderType = .pickImage , _ name: String = "", _ nameType:String = ".png") -> String {
        guard let docPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentationDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).first else {
            return ""
        }
        let savePath = docPath + "/" + folderType.rawValue
        if !FileManager.default.fileExists(atPath: savePath) {
    
            do {
                try FileManager.default.createDirectory(atPath: savePath, withIntermediateDirectories: true, attributes: nil)
            } catch {
                return ""
            }
        }
        let saveName = name.isEmpty ? ("\(Date().timeIntervalSince1970)" as NSString).replacingOccurrences(of:".", with: "") : name
        let path = savePath + "/" + "\(saveName)" + nameType
        self.write(toFile: path, atomically: true)
        return path
    }
    

    7、NSObject 的扩展

    public  extension NSObject
    
    fullClassName():完整类名
    class func fullClassName() -> String {
        return NSStringFromClass(self)
    }
    
    className():类名
    class func className() -> String {
        let className = NSStringFromClass(self)
        if let location = className.range(of: ".")?.upperBound {
            return String(className[location...])
        }
        return className
    }
    

    8、Double 的扩展

    public extension Double
    
    random:得到一个0到1.0的Double随机数(包括1.0)
    public static var random:Double {
        get {
            return Double(arc4random()) / 0xFFFFFFFF
        }
    }
    
    random(lower min: Double, upper max: Double):获取一个min到max的Double随机数
    public static func random(lower min: Double, upper max: Double) -> Double {
        return Double.random * (max - min) + min
    }
    

    9、Float 的扩展

    public extension Float
    
    random:得到一个0到1.0的Float随机数(包括1.0)
    public static var random:Float {
        get {
            return Float(arc4random()) / 0xFFFFFFFF
        }
    }
    
    random(lower min: Float, upper max: Float):获取一个min到max的Float随机数
    public static func random(lower min: Float, upper max: Float) -> Float {
        return Float.random * (max - min) + min
    }
    

    10、CGFloat 的扩展

    extension CGFloat
    
    randomSign:随机获得-1.0或者1.0
    public static var randomSign:CGFloat {
        get {
            return (arc4random_uniform(2) == 0) ? 1.0 : -1.0
        }
    }
    
    random:得到一个0到1.0的CGFloat随机数(包括1.0)
    public static var random:CGFloat {
        get {
            return CGFloat(Float.random)
        }
    }
    
    random(lower min: CGFloat, upper max: CGFloat):获取一个min到max的CGFloat随机数
    public static func random(lower min: CGFloat, upper max: CGFloat) -> CGFloat {
        return CGFloat.random * (max - min) + min
    }
    

    11、String 的扩展

    字符串内容判断
    isEmpty(str: String?):静态方法判断字符串为空
    static func isEmpty(str: String?) -> Bool {
        guard let v = str else {
            return true
        }
        let leftText = v.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
        if leftText == "" {
            return true
        }
        return false
    }
    
    isEmptyString() -> Bool:判断字符串为空
    func isEmptyString() -> Bool {
        let leftText = trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
        if leftText == "" {
            return true
        }
        return false
    }
    
    isMobile() -> Bool:判断是否为手机号
    func isMobile() -> Bool {
        let regex = try! NSRegularExpression(pattern: "^1[0-9]{10}$", options: [.caseInsensitive])
        return regex.firstMatch(in: self, options:[], range: NSMakeRange(0, self.count)) != nil
    }
    
    isEmail() -> Bool:校验邮箱是否合规
    func isEmail() -> Bool {
        let regex = try! NSRegularExpression(pattern: "^(([a-z0-9_-]+\\.)*)([a-z0-9_-]+)@(([a-z0-9-]+\\.)+)([a-z0-9]{2,6})$", options: [.caseInsensitive])
        return regex.firstMatch(in: self, options:[], range: NSMakeRange(0, self.count)) != nil
    }
    
    isVerifyCode() -> Bool:校验验证码是否合规
    func isVerifyCode() -> Bool {
        let regex = try! NSRegularExpression(pattern: "^[0-9]{6}$", options: [.caseInsensitive])
        return regex.firstMatch(in: self, options:[], range: NSMakeRange(0, self.count)) != nil
    }
    
    vaildPassword() -> (bool: Bool, error: String):校验密码是否合规
    func vaildPassword() -> (bool: Bool, error: String) {
        if self.count < 6 || self.count > 16{
            return (false,"密码长度应该为6到16位")
        }
        else if self.contains(" "){
            return (false,"密码不能包含空格")
        }
        else if self.contains("\t"){
            return (false,"密码不能包含制表符")
        }
        else if self.contains("\n"){
            return (false,"密码不能包含回车")
        }
        else{
            return (true,"")
        }
    }
    
    containMobile() -> Bool:校验手机号是否合规
    func containMobile() -> Bool {
        guard let regex = try? NSRegularExpression(pattern: "1[3-8][0-9]{9}", options: [.caseInsensitive]) else {return false}
        let matchNum = regex.numberOfMatches(in: self, options: [], range: NSRange(location: 0, length: (self as NSString).length))
        return matchNum > 0
    }
    
    isChinese() -> Bool:校验是否为中文
    func isChinese() -> Bool {
        let regex = try! NSRegularExpression(pattern: "^[\\u4e00-\\u9fa5]+$", options: [.caseInsensitive])
        return regex.firstMatch(in: self, options:[], range: NSMakeRange(0, self.count)) != nil
    }
    
    validateIDCardNumber() -> Bool:验证身份证是否合规
    func validateIDCardNumber() -> Bool {
        let value = self.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
        let length = value.count
        if (length == 18) {
            let provinceCodeList = ["11","12","13","14","15",
                                "21","22","23",
                                "31","32","33","34","35","36","37",
                                "41","42","43","44","45","46",
                                "50","51","52","53","54",
                                "61","62","63","64","65",
                                "71",
                                "81","82",
                                "91"]
            let regularExpress = try? NSRegularExpression.init(pattern: "^[0-9]{17}[0-9X]$", options: .caseInsensitive)
            if let _ = regularExpress?.firstMatch(in: self, options: .reportProgress, range: NSMakeRange(0, length)) {
                
                // 校验省份是否合规
                let province = self.subString(to: 2)
                if !provinceCodeList.contains(province) {
                    return false
                }
                
                //判断年月日是否有效
                //年份
                let strYear = Int(self.subString(from: 6, length: 4))
                
                //月份
                let strMonth = Int(self.subString(from: 10, length: 2))
                
                //日
                let strDay = Int(self.subString(from: 12, length: 2))
    
                let localZone = NSTimeZone.local
    
                let dateFormatter = DateFormatter()
                dateFormatter.dateStyle = .medium
                dateFormatter.timeStyle = .none
                dateFormatter.timeZone = localZone
                dateFormatter.dateFormat = "yyyy-MM-dd"
                let date = dateFormatter.date(from: "\(String(format: "%02d",strYear!))-\(String(format: "%02d",strMonth!))-\(String(format: "%02d",strDay!))")
    
                if date == nil {
                    return false
                }
                //加权因子
                let R = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
                
                //校验码
                let sChecker: [Int8] = [1,0,10,9,8,7,6,5,4,3,2]
                var sum = 0
                for i in 0...16 {
                    sum += R[i]*(Int(self.subString(from: i, length: 1)) ?? 0)
                }
                let verifyStr = self.subString(from: 17, length: 1)
                var verifyCode = 0
                if verifyStr == "X" {
                    verifyCode = 10
                } else {
                    verifyCode = Int(verifyStr) ?? 0
                }
                let mode = sum % 11
                if sChecker[mode] == verifyCode {
                    return true
                } else {
                    return false
                }
                
            } else {
                return false
            }
        } else {
            return false
        }
    }
    
    字符串操作
    subString(to:Int):截取字符串直到指定终点
    func subString(to:Int) -> String {
        return subString(from: 0,to: to )
    }
    
    subString(from:Int) :从指定起点开始截取字符串
    func subString(from:Int) -> String {
        return subString(from: from,to: self.count - 1)
    }
    
    subString(from:Int,length:Int):从指定起点开始截取一定长度的字符串
    func subString(from:Int,length:Int) -> String {
        let to = from + length
        return subString(from: from,to: to)
    }
    
    subString(from:Int,to:Int):截取从指定起点到指定终点范围之内的字符串
    func subString(from:Int,to:Int) -> String {
        if from >= self.count || to > self.count {
            return self
        } else {
            let startIndex = Index(utf16Offset: from, in: self)
            let endIndex = Index(utf16Offset: to, in: self)
            let subString = self[startIndex ..< endIndex]
            return String(subString)
        }
    }
    
    limitString(limit: Int):根据指定长度截取字符串
    func limitString(limit: Int) -> String {
        return subString(to: limit)
    }
    
    limitStringWithDot(limit: Int) :根据指定长度截取字符串结尾显示...
    func limitStringWithDot(limit: Int) -> String {
        let newStr = NSMutableString(string: self)
        if limit > -1 && newStr.length > limit {
            return newStr.substring(to: limit) + "..."
        } else {
            return self
        }
    }
    
    deleteSpace():删除空格
    func deleteSpace() -> String {
        return self.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
    }
    
    removeAllSpace():移除所有空格
    func removeAllSpace() -> String {
        return self.replacingOccurrences(of: " ", with: "", options: .literal, range: nil)
    }
    
    deleteLineBreak() :移除所有换行符和制表符
    func deleteLineBreak() -> String {
        return self.replacingOccurrences(of: "\n", with: " ").replacingOccurrences(of: "\r", with: " ")
    }
    
    trimmingSpace():截取掉字符串两端的空格和换行符
    func trimmingSpace() -> String {
        return self.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
    }
    
    replaceAllSpace(replacement:String = ""):替换掉字符串中所有空格,默认为移除
    func replaceAllSpace(replacement:String = "") -> String {
        return self.replacingOccurrences(of: " ", with: replacement, options: .literal, range: nil)
    }
    
    replaceLineBreak(replacement:String = " "):替换掉字符串中所有换行符,默认为空格
    func replaceLineBreak(replacement:String = " ") -> String {
        return self.replacingOccurrences(of: "\n", with: replacement).replacingOccurrences(of: "\r", with: replacement)
    }
    
    decodeUrl():URL解码
    func decodeUrl() -> String {
        let mutStr = NSMutableString(string: self)
        mutStr.replaceOccurrences(of: "+", with: " ", options: NSString.CompareOptions.literal, range: NSMakeRange(0, mutStr.length))
        return mutStr.removingPercentEncoding ?? ""
    }
    
    encodeUrl():URL编码
    func encodeUrl() -> String {
        let generalDelimitersToEncode = "!$&'()*+,;=:#[]@/?"
        var allowedCharacterSet = CharacterSet.urlQueryAllowed
        allowedCharacterSet.remove(charactersIn: generalDelimitersToEncode)
        return self.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? ""
    }
    
    urlSetComponents(_ params:[String:String]):URL 字符串拼接
    func urlSetComponents(_ params:[String:String]) -> String {
        var queryItems = [URLQueryItem]()
        params.each { (key, value) in
            let queryItem = URLQueryItem(name: key, value: "\(value)")
            queryItems.append(queryItem)
        }
        let urlComponents = NSURLComponents(string: self)
        urlComponents?.queryItems = queryItems
        
        return urlComponents?.url?.absoluteString ?? ""
    }
    
    urlParameters():从urlString中截取出参数,参数必须经过url编码
    func urlParameters() -> [String: String]? {
        guard let url = URL(string: self),
            let components = URLComponents(url: url, resolvingAgainstBaseURL: true),
            let queryItems = components.queryItems else { return nil }
        return queryItems.reduce(into: [String: String](), { (result, item) in
            result[item.name] = item.value?.decodeUrl()
        })
    }
    
    rangesOfRegex(_ regex: String):获取指定正则条件的range数组
    func rangesOfRegex(_ regex: String) -> [NSRange] {
        let expression = try? NSRegularExpression(pattern: regex, options: .caseInsensitive)
        let matches = expression?.matches(in: self, options: .reportProgress, range: NSMakeRange(0, self.count))
        return matches?.map({ (match) -> NSRange in
            return match.range
        }) ?? []
    }
    
    rangesOfString(_ target: String):获取指定字符串的range数组
    func rangesOfString(_ target: String) -> [NSRange] {
        return self.rangesOfRegex(target)
    }
    
    rangesOfNumber():获取字符串中数字的range数组
    func rangesOfNumber() -> [NSRange] {
        return self.rangesOfRegex("[0-9]+")
    }
    
    pregReplace(pattern: String, with: String):使用正则表达式替换
    func pregReplace(pattern: String, with: String,
                     options: NSRegularExpression.Options = []) -> String {
        let regex = try! NSRegularExpression(pattern: pattern, options: options)
        return regex.stringByReplacingMatches(in: self, options: [],
                                              range: NSMakeRange(0, self.count),
                                              withTemplate: with)
    }
    
    subRangeOfUrl():网址检查
    func subRangeOfUrl() -> [NSRange] {
        let linkPattern = "((http[s]{0,1}|ftp)://[a-zA-Z0-9\\-.]+(?::(\\d+))?(?:(?:/[a-zA-Z0-9\\-._?,'+\\&%$=~*!():@\\\\]*)+)?)|(www.[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?)"
        guard let regex = try? NSRegularExpression(pattern: linkPattern, options: NSRegularExpression.Options.caseInsensitive) else {return []}
        let resultArr = regex.matches(in: self, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSRange(location: 0, length: (self as NSString).length))
        var rangeArr = [NSRange]()
        for item in resultArr {
            rangeArr.append(item.range)
        }
        return rangeArr
    }
    
    subscript (r: Range<Int>):String使用下标截取字符串,比如"示例字符串"[0..<2] 结果是 "示例"
    subscript (r: Range<Int>) -> String {
        get {
            let startIndex = self.index(self.startIndex, offsetBy: r.lowerBound)
            let endIndex = self.index(self.startIndex, offsetBy: r.upperBound)
            return String(self[startIndex..<endIndex])
        }
    }
    
    removeEmoji():移除emoji
    func removeEmoji() -> String {
        let pattern = "[^\\u0020-\\u007E\\u00A0-\\u00BE\\u2E80-\\uA4CF\\uF900-\\uFAFF\\uFE30-\\uFE4F\\uFF00-\\uFFEF\\u0080-\\u009F\\u2000-\\u201f\r\n]"
        return self.pregReplace(pattern: pattern, with: "")
    }
    
    字符串尺寸
    heightForTextSize(fontSize: CGFloat, width: CGFloat):普通系统文本的高度
    func heightForTextSize(fontSize: CGFloat, width: CGFloat) -> CGFloat {
        let font = UIFont.systemFont(ofSize: fontSize)
        return self.heightWithFont(font: font, width: width)
    }
    
    widthForTextSize(fontSize: CGFloat, height: CGFloat = 15):普通系统文本的高度
    func widthForTextSize(fontSize: CGFloat, height: CGFloat = 15) -> CGFloat {
        let font = UIFont.systemFont(ofSize: fontSize)
        return self.widthWithFont(font: font,height: height)
    }
    
    heightWithBoldForTextSize(fontSize: CGFloat, width: CGFloat):加粗系统文本的高度
    func heightWithBoldForTextSize(fontSize: CGFloat, width: CGFloat) -> CGFloat {
        let font = UIFont.boldSystemFont(ofSize: fontSize)
        return self.heightWithFont(font: font, width: width)
    }
    
    widthWithBoldForTextSize(fontSize: CGFloat, height: CGFloat = 15):加粗系统文本的宽度
    func widthWithBoldForTextSize(fontSize: CGFloat, height: CGFloat = 15) -> CGFloat {
        let font = UIFont.boldSystemFont(ofSize: fontSize)
        return self.widthWithFont(font: font,height: height)
    }
    
    heightWithFont(font: UIFont, width: CGFloat):计算字体的高度
    func heightWithFont(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)
    }
    
    widthWithFont(font: UIFont, height: CGFloat = 15):计算字体的宽度
    func widthWithFont(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)
    }
    
    boundingSize():计算字体尺寸
    func boundingSize(withConstraintSize size: CGSize, font: UIFont, lineBreakMode: NSLineBreakMode = .byWordWrapping, option: NSStringDrawingOptions = .usesLineFragmentOrigin, context: NSStringDrawingContext? = nil) -> CGSize{
        return boundingRect(withSize: size, font: font, lineBreakMode: lineBreakMode, option: option, context: context).size
    }
    
    boundingRect():计算字体尺寸的实现方法
    func boundingRect(withSize size: CGSize, font: UIFont, lineBreakMode: NSLineBreakMode = .byWordWrapping, option: NSStringDrawingOptions = .usesLineFragmentOrigin, context: NSStringDrawingContext? = nil) -> CGRect {
        let text = self as NSString
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineBreakMode = lineBreakMode;
        let attributes = [
            NSAttributedString.Key.font:font,
            NSAttributedString.Key.paragraphStyle:paragraphStyle
        ]
        return text.boundingRect(with: size, options: option, attributes: attributes, context: context)
    }
    
    字符串转对象
    stringToDictionary():字符串转字典
    func stringToDictionary() -> [String : Any]? {
        var result: [String : Any]?
        guard !self.isEmpty else { return result }
        guard let dataSelf = self.data(using: .utf8) else {
            return result
        }
        if let dic = (try? JSONSerialization.jsonObject(with: dataSelf, options: JSONSerialization.ReadingOptions.mutableContainers)) as? [String : Any] {
            result = dic
        }
        return result
    }
    
    stringToArray():字符串转数组
    func stringToArray() -> [Any]? {
        var result: [Any]?
        guard !self.isEmpty else { return result }
        guard let dataSelf = self.data(using: .utf8) else {
            return result
        }
        if let array = (try? JSONSerialization.jsonObject(with: dataSelf, options: JSONSerialization.ReadingOptions.mutableContainers)) as? [Any] {
            result = array
        }
        return result
    }
    
    toDouble():字符串转Double类型
    func toDouble() -> Double {
        return Double(self) ?? 0
    }
    
    toFloat():字符串转Float类型
    func toFloat() -> Float {
        return Float(toDouble())
    }
    
    toCGFloat():字符串转CGFloat类型
    func toCGFloat() -> CGFloat {
        return CGFloat(toDouble())
    }
    
    toInt():字符串转Int类型
    func toInt() -> Int {
        return Int(toDouble())
    }
    
    pinyinString():先转换为带音标的拼音,然后去掉音标
    func pinyinString() -> String? {
        let mutableString = NSMutableString(string: self)
        if CFStringTransform(mutableString, nil, kCFStringTransformMandarinLatin, false) {
            if CFStringTransform(mutableString, nil, kCFStringTransformStripDiacritics, false) {
                return NSString(string: mutableString) as String
            }
        }
        return nil
    }
    
    firstChar():第一个字符
    func firstChar() -> String {
        guard let first = self.trimmingCharacters(in: CharacterSet.whitespaces).first else {return ""}
        return "\(first)".uppercased()
    }
    
    返回NSAttributedString
    setColor(subString: String,withColor color: UIColor,withFont font: UIFont):设置子字符串属性字体
    func setColor(subString: String,withColor color: UIColor,withFont font: UIFont) -> NSMutableAttributedString {
        let tempNSString: NSString = self as NSString
        let range = tempNSString.range(of: subString)
        return self.setColor(range: range, withColor: color, withFont: font)
    }
    
    setColor(range: NSRange, withColor: UIColor, withFont: UIFont):设置某个范围内的属性字体
    func setColor(range: NSRange, withColor: UIColor, withFont: UIFont) -> NSMutableAttributedString {
        let tempNSString: NSString = self as NSString
        let attributedString = NSMutableAttributedString(string: tempNSString as String)
        attributedString.addAttribute(NSAttributedString.Key.font, value: withFont, range: range)
        attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: withColor, range: range)
        return attributedString
    }
    
    attributedStringWithLineSpacing(lineSpacing: CGFloat):字符串配置文字行间距
    func attributedStringWithLineSpacing(lineSpacing: CGFloat) -> NSMutableAttributedString {
        let attributedString = NSMutableAttributedString(string: self)
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineSpacing = lineSpacing
        attributedString.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: NSMakeRange(0, (self as NSString).length))
        return attributedString
    }
    
    字符串哈希值
    filePathSha256():文件路径哈希值
    func filePathSha256() -> String {
        let fileManager = FileManager.default
        if let url = URL.init(string: self) {
            if fileManager.fileExists(atPath: url.path) {
                let txtData = fileManager.contents(atPath: url.path)
                return hexStringFromData(input: digest(input: txtData! as NSData))
            }
        }
        return ""
    }
    
    hexStringFromData(input: NSData):从数据中获取到哈希字符串
    private func hexStringFromData(input: NSData) -> String {
        var bytes = [UInt8](repeating: 0, count: input.length)
        input.getBytes(&bytes, length: input.length)
    
        var hexString = ""
        for byte in bytes {
            hexString += String(format:"%02x", UInt8(byte))
        }
    
        return hexString
    }
    
    digest(input : NSData):获取数据的SHA256加密
    import CommonCrypto
    
    private func digest(input : NSData) -> NSData {
        let digestLength = Int(CC_SHA256_DIGEST_LENGTH)
        var hash = [UInt8](repeating: 0, count: digestLength)
        CC_SHA256(input.bytes, UInt32(input.length), &hash)
        return NSData(bytes: hash, length: digestLength)
    }
    

    12、Timer 的扩展

    public extension Timer
    
    schedule(intervalFromNow: TimeInterval, block: @escaping () -> ()):只执行一次的计时器
    @discardableResult
    class func schedule(intervalFromNow: TimeInterval, block: @escaping () -> ()) -> Timer {
        let actor = TimerActor(block: block)
        let timer = Timer.init(timeInterval: intervalFromNow, target: actor, selector: #selector(actor.fire), userInfo: nil, repeats: false)
        RunLoop.current.add(timer, forMode: RunLoopMode.commonModes)
        return timer
    }
    
    schedule(every interval: TimeInterval, block: @escaping () -> ()):重复执行的计时器
    @discardableResult
    class func schedule(every interval: TimeInterval, block: @escaping () -> ()) -> Timer {
        let actor = TimerActor(block: block)
        let timer = Timer.init(timeInterval: interval, target: actor, selector: #selector(fire), userInfo: nil, repeats: true)
        RunLoop.current.add(timer, forMode: RunLoopMode.commonModes)
        return timer
    }
    
    TimerActor:计时器的中介者对象
    private class TimerActor {
        var block: () -> ()
        
        init(block: @escaping () -> ()) {
            self.block = block
        }
        
        @objc dynamic func fire() {
            block()
        }
    }
    

    相关文章

      网友评论

          本文标题:Swift:NSObject 扩展工具箱

          本文链接:https://www.haomeiwen.com/subject/mfrccrtx.html