如何按创建 UITableViewCell 时计算的值对 UITableView 进行排序?

Posted

技术标签:

【中文标题】如何按创建 UITableViewCell 时计算的值对 UITableView 进行排序?【英文标题】:How can I sort a UITableView by a value that's calculated when a UITableViewCell is created? 【发布时间】:2017-05-28 14:46:43 【问题描述】:

我的应用程序中有一个UITableView,它显示了LiftEvent 类型的NSManagedObjects 的一长串列表,它们位于NSFetchedResultsController 中。然而,显示的值之一不是存储属性,它是通过在创建 UITableViewCell 的视图模型时(在 extension 中)调用对象上的方法来计算的:

class LiftLogTableViewCell: UITableViewCell 

    @IBOutlet weak var liftName: UILabel!
    @IBOutlet weak var liftDetails: UILabel!
    @IBOutlet weak var liftDate: UILabel!
    @IBOutlet weak var oneRepMaxWeight: UILabel!
    @IBOutlet weak var unit: UILabel!
    @IBOutlet weak var formula: UILabel!

    var liftWeight: String!
    var repetitions: String!

    struct ViewData 
        let liftName: String
        let liftWeight: Double
        let repetitions: Int
        let liftDate: String
        let oneRepMaxWeight: Double
        let unit: String
        let formula: String
    

    var viewData: ViewData! 
        didSet 
            liftName!.text = viewData.liftName
            liftWeight = String(viewData.liftWeight)
            repetitions = String(viewData.repetitions)

            let formatter = StringFormatter()
            let formattedWeightLifted = formatter.formatForDisplay(viewData.liftWeight)
            liftDetails!.text = "\(formattedWeightLifted) @ \(viewData.repetitions)"
            liftDate!.text = "on \(viewData.liftDate)"
            oneRepMaxWeight!.text = "\(viewData.oneRepMaxWeight)"
            unit!.text = viewData.unit
            formula!.text = viewData.formula
        
    


extension LiftLogTableViewCell.ViewData 
    init(liftEvent: LiftEvent) 
        self.liftName = liftEvent.lift.liftName

        // liftEvent.calculatOneRepMax() uses two stored properties of the LiftEvent to calculate the value
        let oneRepMax = liftEvent.calculateOneRepMax() 

        if liftEvent.liftWeight.unit.symbol == UserDefaults.weightUnit() 
            self.liftWeight = liftEvent.liftWeight.value
            self.oneRepMaxWeight = oneRepMax.value
            self.unit = oneRepMax.unit.symbol
                 else 
                    let convertedLiftWeight = ConvertWeightService().convertToOtherUnit(weight: liftEvent.liftWeight)
                    self.liftWeight = convertedLiftWeight.value
                    let convertedMaxWeight = ConvertWeightService().convertToOtherUnit(weight: oneRepMax)
                    self.oneRepMaxWeight = convertedMaxWeight.value
                    self.unit = convertedMaxWeight.unit.symbol
        

        self.repetitions = Int(liftEvent.repetitions)
        self.formula = liftEvent.formula.formulaName
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd"
        let formattedDate = dateFormatter.string(from: liftEvent.date as Date)
        self.liftDate = "\(formattedDate)"

    

我完成了我的作业,发现两年前的 thread 和四年多前的另一个 thread 说使用 NSFecthedResultsController 时无法完成,但 Swift 变化如此之快我想知道现在是否有可能。我已经阅读了 Apple 的文档,但我看不到这样做的方法,但我对这个 API 还是很陌生。

有没有办法使用NSFetchedResultsController 来做到这一点,还是我必须放弃它并使用一个简单的数组?

【问题讨论】:

【参考方案1】:

swift 没有什么神奇之处,它可以让您创建一个 fetchedResultsController,它按未存储在核心数据中的属性排序。有三种可能的解决方案:

    按具有相同顺序的不同属性排序。例如,您可以按date 排序,然后按day 显示,即使day 不是属性,它是date 的派生属性。您甚至可以将day 用作sectionNameKeyPath。 将值存储为常规属性。如果它是从其他属性派生的,那么您必须在其他属性更新时对其进行更新。 在执行 fetch 后进行内存排序。

1 是最好的解决方案,但我不了解您的模型是否可能。如果不可能,我会推荐 2。一般来说,只从一个地方更新您的模型是一种很好的做法,因此添加代码来同步您的派生属性不应该那么繁重。

【讨论】:

谢谢,乔恩。具有讽刺意味的是,我最近重构了我的代码以停止将值存储为常规属性,因为结果数字可以由用户在磅和千克之间转换,并且有可能引入舍入错误。

以上是关于如何按创建 UITableViewCell 时计算的值对 UITableView 进行排序?的主要内容,如果未能解决你的问题,请参考以下文章

Access 2013 - 在添加任何新字段时计算字段值

由于编译时计算的值,如何避免“无法访问的语句”?

如何在渲染时计算数组 [Vue.js] - 无限循环错误

PHP MYSQL如何在选择时计算项目[重复]

仅在满足条件时计算 udf [重复]

ansys分析时计算出来的应力和应变的单位分别是多少?