Динамически меняющаяся функция cell.update Date? - PullRequest
0 голосов
/ 04 мая 2019

Я только новичок во всем этом, так что прости мое невежество!У меня есть 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)
            }
        }
    }

Вот функция Table View (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
    }

1 Ответ

0 голосов
/ 04 мая 2019
  1. Если код работает, он не может быть плохим.
  2. Хорошая идея - написать модульные тесты и тесты производительности перед любой оптимизацией производительности. Таким образом, вы увидите, что ваши изменения не влияют на результат и улучшают производительность. Также вы можете использовать инструменты XCode, чтобы понять, как именно ваш код использует ЦП и память, нажав Product-> Profile и выбрав Time profile и Allocations tools. Не забывайте, что оптимизация производительности часто является компромиссом между использованием памяти и процессора.
  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)
   }

Или вы можете сохранить DateMapper в ViewController и использовать его непосредственно в cellForRowAt. * ​​1015 *

  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
        }
    }
    

На консоли вы увидите, сколько времени займет преобразование даты в строку:

значения: [0,000922, 0,000063, 0,000041, 0,000038, 0,000036, 0,000035, 0,000035, 0,000036, 0,000043, 0,000027]

...