博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
DateFormatter的优化
阅读量:6998 次
发布时间:2019-06-27

本文共 5558 字,大约阅读时间需要 18 分钟。

我想,作为一个iOS开发人员,你应该知道***DateFormatter***的实例创建操作,是多么的昂贵。 在这篇文章中,我想看一下创建***DateFormatter***实例的成本以及如何有效的缓存他们。

###实验 1.***DateFormatter***为每个日期转换创建一个新的实例。 2.***DateFormatter***对所有日期转换重复使用相同的实例。

class DateConverter {        let dateFormat = "y/MM/dd @ HH:mm"        func convertDatesWithUniqueFormatter(_ dates: [Date]) {                for date in dates {            let dateFormatter = DateFormatter()            dateFormatter.dateFormat = dateFormat            _ = dateFormatter.string(from: date)        }    }        func convertDatesWithReusedFormatter(_ dates: [Date]) {        let dateFormatter = DateFormatter()        dateFormatter.dateFormat = dateFormat                for date in dates {            _ = dateFormatter.string(from: date)        }            }    }复制代码

***convertDatesWithUniqueFormatter***代表第一个场景,***convertDatesWithReusedFormatter***第二个场景。两种方法都遵循类似的结构 - 循环遍历日期数组并将每个日期格式化为字符串表示形式,唯一的区别在于如何***DateFormatter***使用。

我们用单元测试来测试一下性能:

import XCTest@testable import Practiceclass PracticeTests: XCTestCase {    var sut:DateConverter!    let dates = Array(repeating: Date(), count: 100)            override func setUp() {        // Put setup code here. This method is called before the invocation of each test method in the class.           sut = DateConverter()    }    override func tearDown() {        // Put teardown code here. This method is called after the invocation of each test method in the class.           sut = nil    }        func test_convertDatesWithUniqueFormatter_performance() {                measure {            sut.convertDatesWithUniqueFormatter(dates)        }    }        func test_convertDatesWithReusedFormatter_performance() {                measure {            sut.convertDatesWithReusedFormatter(dates)        }    }    func testExample() {        // This is an example of a functional test case.        // Use XCTAssert and related functions to verify your tests produce the correct results.        }    func testPerformanceExample() {        // This is an example of a performance test case.        self.measure {            // Put the code you want to measure the time of here.        }    }}复制代码

场景一:

场景二:

从数据可以看出,如果重复创建的话,基本上每次耗时平均为0.039,但是,如果复用的话,基本上,第二次及以后,可以缩短20%的时间。可见,***DateFormatter***的创建是多么的耗时。

###如何使用高性能的DateFormatter 既然已经确定重用DateFormatter实例可以提高性能,并且我们已经确定这种性能改进将带来更好的用户体验,那么问题是: “我们如何重用它?” 很简单,可以将DateFormatter实例提取到局部变量或私有属性中,因此可以重用它。

class DateFormattingHelper {        static let shared = DateFormattingHelper()        static let dobDateFormatter: DateFormatter = {        let dateFormatter = DateFormatter()        dateFormatter.dateFormat = "y/MM/dd @ HH:mm"        return dateFormatter    }()        func formatDOB(_ date:Date, with dateFormatter: DateFormatter) -> String {        let formattedDate = dateFormatter.string(from: date)        return "Date of birth:\(formattedDate)"    }}复制代码

调用:

let dateFormatter = DateFormattingHelper.shared.dobDateFormatter        let dobFormattedString = DateFormattingHelper.shared.formatDOB(Date(), with: dateFormatter)        print(dobFormattedString)复制代码

只要我们在使用的时候,传入***DateFormatter:***就可以了,但是,这有个弊端,如果我们多个format格式怎么办呢?创建多个这个的static 属性???

###更优雅的办法

class CachedDateFormattingHelper {    // MARK: - Shared        static let shared = CachedDateFormattingHelper()        // MARK: - Queue        let cachedDateFormattersQueue = DispatchQueue(label: "com.boles.date.formatter.queue")        // MARK: - Cached Formatters        private var cachedDateFormatters = [String : DateFormatter]()        private func cachedDateFormatter(withFormat format: String) -> DateFormatter {        return cachedDateFormattersQueue.sync {            let key = format            if let cachedFormatter = cachedDateFormatters[key] {                return cachedFormatter            }                        let dateFormatter = DateFormatter()            dateFormatter.locale = Locale(identifier: "en_US_POSIX")            dateFormatter.dateFormat = format                        cachedDateFormatters[key] = dateFormatter                        return dateFormatter        }    }        // MARK: - DOB        func formatDOBDate(_ date: Date) -> String {        let dateFormatter = cachedDateFormatter(withFormat: "y/MM/dd @ HH:mm")        let formattedDate = dateFormatter.string(from: date)        return ("Date of birth: \(formattedDate)")    }        // MARK: - Account        func formatLastActiveDate(_ date: Date, now: Date = Date()) -> String {        let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: now)!                var dateFormatter = cachedDateFormatter(withFormat: "dd MMM @ HH:mm")        if date > yesterday {            dateFormatter = cachedDateFormatter(withFormat: "HH:mm")        }                let formattedDate = dateFormatter.string(from: date)        return ("Last active: \(formattedDate)")    }        // MARK: - Post        func formatPostCreatedDate(_ date: Date) -> String {        let dateFormatter = cachedDateFormatter(withFormat: "d MMM 'of' y")        let formattedDate = dateFormatter.string(from: date)        return formattedDate    }        // MARK: - Commenting        func formatCommentedDate(_ date: Date) -> String {        let dateFormatter = cachedDateFormatter(withFormat: "dd MMM @ HH:mm")        let formattedDate = dateFormatter.string(from: date)        return ("Comment posted: \(formattedDate)")    }}复制代码

我们用一个字典,把对应的创建过的格式的formatter存起来,每次,只要去查一下,有没有生成过这种格式的formatter,有就拿来用,没有就创建保存,并且返回出去,这样下次同样的格式就有了。这样是不是很智能,很酷???

来吧,改造你的DateFormatter吧!!!!

转载于:https://juejin.im/post/5cb976f95188251afd79b412

你可能感兴趣的文章
Redis具体解释
查看>>
thinkphp中cookie和session中操作数组的方法
查看>>
rman备份OBSOLETE和EXPIRED参数来历及区别
查看>>
NewLife.Redis基础教程
查看>>
BlockingQueue(阻塞队列)详解
查看>>
Hystrix快速入门
查看>>
十大励志电影
查看>>
在Sql语句中使用正则表达式来查找你所要的字符
查看>>
18种最实用的网站推广方法大全
查看>>
浅谈C/C++中的typedef和#define
查看>>
浅谈C/C++中的指针和数组(一)
查看>>
这该死的数字化生活
查看>>
matlab练习程序(圆柱投影)
查看>>
需要谨记的产品设计原则
查看>>
checkbox实现单选多选
查看>>
billing是如何的拆分的?
查看>>
Lua 迭代器与closure
查看>>
mybatis_helloworld(2)_源码
查看>>
完整部署CentOS7.2+OpenStack+kvm 云平台环境(3)--为虚拟机指定固定ip
查看>>
BLE 广播数据解析
查看>>