**更新:添加了更多代码
我的控制器正在调用我的主要类练习,以根据我的数据模型获取值。数据模型包含许多其他类,这些类进行计算并包含主类的数据结构对象。我觉得我必须做很多代码重复,比如Exercise.getLastWorkout()然后调用我的WorkoutDiary.getLastWorkout()来实际检索锻炼。
从技术上讲,一切正常,但我觉得我错过了一个抽象的概念。子类化可以通过提供继承函数来帮助我吗?
我的代码在这里:https://github.com/briancl2/WorkoutTracker/tree/master/Workout%20Tracker
我的控制器是一个好看的地方,我从我的模型中请求值:https://github.com/briancl2/WorkoutTracker/blob/master/Workout%20Tracker/ExerciseDetailViewController.swift
这是我模型的界面: https://github.com/briancl2/WorkoutTracker/blob/master/Workout%20Tracker/Exercise.swift
该模型调用了许多其他类来在其中创建必要的数据结构(WorkoutDiary)并执行计算(PerformanceAnalyzer)。
WorkoutDiary类也调用其他类的相关数据结构(Workout,它调用Set ...所以抽象继续)
这是一个合适的设计范例吗?我正在构建这个应用程序作为学习体验,所以我认识到我过度设计了这样一个简单的应用程序(跟踪锻炼)。这是我的意图。但是,我想让设计原则正确。
class ExerciseDetailViewController: UIViewController {
@IBOutlet weak var display: UILabel!
// This value is either passed by `ExerciseTableViewController` in `prepareForSegue(_:sender:)`
var exercise: Exercise?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
displayExercise()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func displayExercise() {
if let exercise = exercise {
navigationItem.title = exercise.name
let currentWeights = exercise.currentWeights
let warmup25Text = String(currentWeights.warmup25) + " " + exercise.getBarWeightsString(currentWeights.warmup25)
let warmup50Text = String(currentWeights.warmup50) + " " + exercise.getBarWeightsString(currentWeights.warmup50)
let heavyText = String(currentWeights.heavy) + " " + exercise.getBarWeightsString(currentWeights.heavy)
if let notes = exercise.notes {
display.text! = "Notes:\n"
display.text! += "\(notes)\n"
display.text! += "\n"
}
display.text! += "Warmup (25%): \(warmup25Text)\n"
display.text! += "Warmup (50%): \(warmup50Text)\n"
display.text! += "Heavy (100%): \(heavyText)\n"
display.text! += "\n"
if let lastWorkout = exercise.getOldestWorkoutFromRange(15) {
display.text! += "\(NSDateToPrettyString(lastWorkout.date)) Reps @\(lastWorkout.sets[0].weight): \(lastWorkout.sets[0].repCount) and \(lastWorkout.sets[1].repCount)\n"
}
if let lastWorkout = exercise.getLastWorkout() {
display.text! += "\(NSDateToPrettyString(lastWorkout.date)) Reps @\(lastWorkout.sets[0].weight): \(lastWorkout.sets[0].repCount) and \(lastWorkout.sets[1].repCount)\n"
display.text! += "\n"
display.text! += "15-day total volume increase: \(exercise.getTotalVolumeIncrease(15))%"
display.text! += "\n"
}
}
}
}
我的控制器:
class Workout: NSObject, NSCoding {
var date: NSDate
var sets: [Set]
init(date: NSDate, sets: [Set]) {
self.date = date
self.sets = sets
}
struct PropertyKey {
static let dateKey = "Workout_date"
static let setsKey = "Workout_sets"
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(date, forKey: PropertyKey.dateKey)
aCoder.encodeObject(sets, forKey: PropertyKey.setsKey)
}
required convenience init?(coder aDecoder: NSCoder) {
let date = aDecoder.decodeObjectForKey(PropertyKey.dateKey) as! NSDate
let sets = aDecoder.decodeObjectForKey(PropertyKey.setsKey) as! [Set]
self.init(date: date, sets: sets)
}
}
锻炼课,我的模型的一部分,WorkoutDiary使用的核心数据结构,存储在练习中:
class WorkoutDiary: NSObject, NSCoding {
var diary: [Workout] = []
init(diary: [Workout]) {
self.diary = diary
}
struct PropertyKey {
static let diaryKey = "WorkoutDiary_diary"
}
func addWorkout(workout: Workout) {
diary.append(workout)
}
func getLastWorkout() -> Workout? {
return diary.last
}
func getOldestWorkoutFromRange(dateRange: Int? = nil) -> Workout? {
// if diary is empty, return nil
if diary.count == 0 {
return nil
}
// if an argument was passed
if let dateRange = dateRange {
let daysAgo = calcDaysAgo(dateRange)
// iterate through Diary in reverse to find first workout that is older than dateRange
for workout in diary.reverse() {
// find the first workout that is older than our dateRange
if workout.date < daysAgo {
// if that workout happens to be our last workout, return nil
if workout == diary.last {
return nil
}
// otherwise, return the workout just ahead of the matched workout
return diary[diary.indexOf(workout)!+1]
}
}
// if we don't find any workouts that are older than our range, return the first
return diary.first
} else {
// if no argument, just return the first element
return diary.first
}
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(diary, forKey: PropertyKey.diaryKey)
}
required convenience init?(coder aDecoder: NSCoder) {
let diary = aDecoder.decodeObjectForKey(PropertyKey.diaryKey) as! [Workout]
self.init(diary: diary)
}
以下是锻炼的地方:
{{1}}