【问题标题】:Dynamically changing cell.update Date function?动态改变 cell.update 日期函数?
【发布时间】:2019-09-22 14:38:16
【问题描述】:

我对这一切都是新手,所以请原谅我的无知!我有一个Table View,每次打开场景时我都会调用一个单元格更新方法(它按日期排序)。我试图根据上次编辑对象的时间动态显示不同的日期格式。示例:如果日期是今天,则显示时间,如果日期是昨天,则显示“昨天”等。我的问题是 - 编写此代码的最佳方法是什么,并且在我的 cell.update 调用中调用以下函数会占用大量内存?我怎样才能更好地写这个?任何帮助将不胜感激!

func update(with fitnessInfo: Fitness) {
    if let date = fitnessInfo.dateEdited as Date? {
        let today = Calendar.current.isDateInToday(date)
        let yesterdayFunc = Calendar.current.isDateInYesterday(date)
        let yesterday = date.addingTimeInterval(172800)
        let withinSevenDays = date.addingTimeInterval(604800)
        let dateFormatter = DateFormatter()

        func setdate(_ dateFormatter: DateFormatter) {
            let convertedDate = dateFormatter.string(from: date)
            fitnessDateLabel.text = convertedDate
        }
        if today == true {
            dateFormatter.dateFormat = "h:mm a"
            setdate(dateFormatter)
        } else if yesterdayFunc == true {
            fitnessDateLabel.text = "Yesterday"
        } else {
            switch date {
            case yesterday...withinSevenDays:
                dateFormatter.dateFormat = "EEEE"
                setdate(dateFormatter)
            default:
                dateFormatter.dateFormat = "MMMM dd, yyyy"
                setdate(dateFormatter)
            }
        }
    }

这是调用它的表视图函数 (cellForRowAt)。

tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: “fitnessCell", for: indexPath) as! FitnessTableViewCell
        let fitnessInfo = fetchedRC.object(at: indexPath)
        cell.update(with: fitnessInfo)
        return cell
    }

【问题讨论】:

  • 这段代码是不是 cell.update 函数的一部分?你能展示一下你是如何调用 cell.update 函数的吗?
  • 嗨 @AntonVlasov 我已经添加了我的 Table View cellForRowAt 函数,我从中调用它。
  • 所以你的代码可以工作,但你想提高它的性能?
  • @AntonVlasov 是的,我只是不确定这是否适用于在多个数据单元格上调用更新函数的真实场景。另外,如果 if 和 case 块可以用另一种方式编写,那么它会更简洁吗?

标签: ios swift uitableview date nsdate


【解决方案1】:
  1. 如果代码可以正常工作,那也不错。
  2. 最好在进行任何性能优化之前编写单元测试和性能测试。因此,您将看到您的更改不会影响结果并提高性能。您还可以使用 Xcode 工具来了解您的代码究竟如何使用 CPU 和内存,方法是单击产品->配置文件并选择时间配置文件和分配工具。不要忘记,性能优化通常是内存和 CPU 使用率之间的权衡。
  3. 您应该将逻辑与演示分开。所以你可以编写单元测试。您也可以静态保留 DateFrommater,而不是在每次绘制单元格时对其进行初始化。这是一个如何完成的示例:

    final class DateMapper {
        static let todayDateFormatter = DateFormatter()
        static let lastWeekAgoDateFormatter = DateFormatter()
        static let moreThanWeekAgoDateFormatter = DateFormatter()
        let today: Date
        let currentCalendar = Calendar.current
    
        init(today: Date) {
            self.today = today
            DateMapper.todayDateFormatter.dateFormat = "h:mm a"
            DateMapper.lastWeekAgoDateFormatter.dateFormat = "EEEE"
            DateMapper.moreThanWeekAgoDateFormatter.dateFormat = "MMMM dd, yyyy"
        }
    
        func formattedDate(date: Date) -> String {
            guard let totalDays = currentCalendar.dateComponents([.day], from: date, to: today).day else {
                return ""
            }
            switch totalDays {
            case 0:
                return DateMapper.todayDateFormatter.string(from: date)
            case 1:
                return "Yesterday"
            case 2...7:
                return DateMapper.lastWeekAgoDateFormatter.string(from: date)
            default:
                return DateMapper.moreThanWeekAgoDateFormatter.string(from: date)
            }
        }
    }
    

这个类可以像这样在你的更新方法中使用:

  func update(with fitnessInfo: Fitness) {
       let dateMapper = DateMapper(today: Date())
       fitnessDateLabel.text = dateMapper.formattedDate(date: fitnessInfo.dateEdited)
   }

或者你可以在 ViewController 中保留 DateMapper 并在 cellForRowAt 中直接使用它。

  1. 这个类可以被单元测试覆盖:

    class ExampleTests: XCTestCase {
    
        var dateMapper: DateMapper {
            let todayStub = dateStubByComponents(year: 2019, month: 5, day: 4, hour: 12)
            return DateMapper(today: todayStub)
        }
    
        func testTodayDate() {
            // arrange
            let todayStub = dateStubByComponents(year: 2019, month: 5, day: 4, hour: 11)
    
            // act
            let result = dateMapper.formattedDate(date: todayStub)
    
            // assert
            XCTAssertEqual(result, "11:00 AM")
        }
    
        func testYestadayDate() {
            // arrange
            let yesterdayStub = dateStubByComponents(year: 2019, month: 5, day: 3, hour: 0)
    
            // act
            let result = dateMapper.formattedDate(date: yesterdayStub)
    
            // assert
            XCTAssertEqual(result, "Yesterday")
        }
    
        func testLastWeekDate() {
            // arrange
            let lastWeekStub = dateStubByComponents(year: 2019, month: 5, day: 2, hour: 0)
    
            // act
            let result = dateMapper.formattedDate(date: lastWeekStub)
    
            // assert
            XCTAssertEqual(result, "Thursday")
        }
    
        func testPerformanceExample() {
            let lastWeekStub = dateStubByComponents(year: 2019, month: 5, day: 2, hour: 0)
            self.measure {
                 _ = dateMapper.formattedDate(date: lastWeekStub)
            }
        }
    
        // MARK: Private
    
        private func dateStubByComponents(year: Int, month: Int, day: Int, hour: Int) -> Date {
        var dateStubComponents = DateComponents()
        dateStubComponents.year = year
        dateStubComponents.month = month
        dateStubComponents.day = day
        dateStubComponents.hour = hour
    
        guard let dateStub = Calendar.current.date(from: dateStubComponents) else { fatalError("Date must be valid") }
           return dateStub
        }
    }
    

在控制台中,您将看到将 Date 转换为 String 需要多长时间:

值:[0.000922, 0.000063, 0.000041, 0.000038, 0.000036, 0.000035, 0.000035, 0.000036, 0.000043, 0.000027]

【讨论】:

    猜你喜欢
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-03
    • 1970-01-01
    • 1970-01-01
    • 2017-07-26
    • 1970-01-01
    相关资源
    最近更新 更多