如何减少存储在Realm中的嵌套对象的可变性?

时间:2016-05-24 22:57:35

标签: swift functional-programming realm

Full code on github

我正在尝试重写我的应用程序以减少可变性并利用函数式编程。我无法确定从哪里开始,因为我的架构似乎几乎无处不在地使用修改。我可以在一个简单的起点上使用一些建议,如何将其分解为更小的部分,我在每次修改时保持不变性。我应该更改我的数据存储架构,以便我只存储/修改/删除叶对象吗?

现在,从根ViewController,我加载了我的一个怪物对象ExerciseProgram(其中包含RealmListExercise个对象,其中包含RealmListWorkouts 1}},其中包含RealmList Sets ....)

final class ExerciseProgram: Object {
    dynamic var name: String = ""
    dynamic var startDate = NSDate()
    dynamic var userProfile: User?
    var program = List<Exercise>()
    var count: Int {
        return program.count
    }
}

在MasterTableViewController.swift中加载一次:

func load() -> ExerciseProgram? {
    let realm = try! Realm()
    return realm.objects(ExerciseProgram).first
}

然后在整个应用中修改单个ExerciseProgram对象,例如录制新的锻炼时。

要创建新的Workout,我在RecordWorkoutTableViewController.swift中实例化一个新的Workout对象:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if doneButton === sender {
        if let date = newDate, weight = newWeight, setOne = newSetOne, setTwo = newSetTwo {
            let newSets = List<WorkSet>()
            newSets.append(WorkSet(weight: weight, repCount: setOne))
            newSets.append(WorkSet(weight: weight, repCount: setTwo))
            newWorkout = Workout(date: date, sets: newSets)
        }
    }
}

解除对ExerciseDetailTableViewController.swift的影响,其中存储发生在开头检索到的同一个怪物ExerciseProgram对象中:

@IBAction func unwindToExerciseDetail(sender: UIStoryboardSegue) {
    if let sourceViewController = sender.sourceViewController as? RecordWorkoutTableViewController, newWorkout = sourceViewController.newWorkout {
        let realm = try! Realm()
        try! realm.write {
            exercise.recordWorkout(newWorkout)
        }
    }
}

此行为在我的应用中被复制。如果我想编辑或删除现有的锻炼,则它完全相同。

Exercise类就是这样:

final class Exercise: Object {
    dynamic var name = ""
    dynamic var notes: String?
    var workoutDiary = List<Workout>()
    dynamic var goal = 0

    ...

    func recordWorkout(newWorkout: Workout) {
        workoutDiary.append(newWorkout)
    }

    func replaceWorkout(originalWorkout: Workout, newWorkout: Workout) {
        workoutDiary[workoutDiary.indexOf(originalWorkout)!] = newWorkout
    }
}

1 个答案:

答案 0 :(得分:2)

据我所知,看看那个架构,不,你不应该改变它。如果它正确地表示了信息类型及其关系,并且它已经在您的应用中运行,那么就无需更改它。

如果您觉得它过于复杂或令人困惑,那么在对代码本身进行更多工作之前,可能需要返回并查看您的数据模型设计本身。检查链接对象中的每个关系和每个属性,并确保在该级别保存数据绝对至关重要。在任何情况下,Realm本身都非常擅长处理对象之间的关系,所以它并不是错误的&#39;有几层嵌套对象。

无论哪种方式,Realm本身都非常适合函数式编程,因为每个属性都是明确不可改变的。函数式编程并不意味着一切都必须是不可变的。不可避免地,你必须达到你需要保存对Realm的更改的程度;它背后的思维方式是,当你正在处理数据时,你并没有改变数据,而是最大限度地减少了实际执行数据的点数。