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

时间:2017-05-28 14:46:44

标签: swift sorting core-data nsfetchedresultscontroller

我的应用中有一个UITableView,其中显示了NSManagedObjectsLiftEvent类型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时无法完成,但斯威夫特的变化如此之快,我想知道现在是否可能。我已经阅读了Apple的文档,我看不到这样做的方法,但我对这个API很陌生。

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

1 个答案:

答案 0 :(得分:0)

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

  1. 按具有相同顺序的其他属性排序。例如,您可以按date排序,然后按day显示,即使day不是属性,它也是date的派生属性。您甚至可以将day用作sectionNameKeyPath
  2. 将值存储为常规属性。如果它是从其他属性派生的,那么只要更新其他属性,就必须更新它。
  3. 执行提取后执行内存中排序。
  4. 1是最好的解决方案,但我不明白你的模型是否有可能。如果不可能,我会建议2.一般来说,最好只从一个地方更新模型,因此添加代码来同步派生属性不应该太繁重。