【发布时间】:2019-11-24 01:23:37
【问题描述】:
这就是我的 Realm 类的样子:
class Workout: Object {
@objc dynamic var date: Date? // Date I did the exercise
@objc dynamic var exercise: String? // Name of exercise, example; Bench Press, Squat, Deadlift etc..
// List of sets (to-many relationship)
var sets = List<Set>()
}
class Set: Object {
@objc dynamic var reps: Int = 0 // Number of reps for the each set
@objc dynamic var kg: Double = 0.0 // Amount of weight/kg for each set
@objc dynamic var notes: String? // Notes for each set
// Define an inverse relationship to be able to access your parent workout for a particular set (if needed)
var parentWorkout = LinkingObjects(fromType: Workout.self, property: "sets")
convenience init(numReps: Int, weight: Double, aNote: String) {
self.init()
self.reps = numReps
self.kg = weight
self.notes = aNote
}
}
我想从我上次做这个练习时获得每组的重量(公斤)和重复次数。所以我正在尝试这样的事情。要使用exercise“Text Exercise2”查询锻炼,我这样做:
func queryFromRealm() {
let realm = try! Realm()
let getExercises = realm.objects(Workout.self).filter("exercise = 'Text Exercise2'").sorted(byKeyPath: "date",ascending: false)
print(getExercises.last!)
myTableView.reloadData()
}
这给了我这样的输出:
Workout {
date = 2019-11-24 00:33:21 +0000;
exercise = Text Exercise2;
sets = List<Set> <0x600003fcdb90> (
[0] Set {
reps = 12;
kg = 7;
notes = light workout;
},
[1] Set {
reps = 12;
kg = 8;
notes = medium workout;
},
[2] Set {
reps = 12;
kg = 9;
notes = heavy workout;
}
);
}
这就是我将数据从 mainVC 传递到 ExerciseCreatorViewController 的方式:
var selectedWorkout = Workout()
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "toEditExerciseCreatorSegue" {
if let nextVC = segue.destination as? ExerciseCreatorViewController {
nextVC.selectedWorkout = self.selectedWorkout
}
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
selectedWorkout = resultFromDate[indexPath.row]
performSegue(withIdentifier: "toEditExerciseCreatorSegue", sender: self)
}
从现在开始,我想将这些添加到UITableView,其中每一行包含公斤和代表次数。我怎样才能做到这一点?我应该以某种方式更改我的设置吗?期待您的帮助。
编辑 - 上传了整个 ExerciseCreatorViewController.swift 文件:
import UIKit
import RealmSwift
class ExerciseCreatorViewController: UIViewController, UITextFieldDelegate, UITableViewDelegate, UITableViewDataSource {
let menuButtonSize: CGSize = CGSize(width: 44, height: 44)
let actionButtonSize: CGSize = CGSize(width: 44, height: 66)
let screenSize: CGRect = UIScreen.main.bounds
var resultFromDate:[Workout] = []
var selectedWorkout = Workout()
@IBOutlet var exerciseNameTextField: UITextField!
let exerciseName = UILabel()
@IBOutlet var navView: UIView!
let navLabel = UILabel()
@IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
exerciseNameTextField.delegate = self
// Get main screen bounds
let screenSize: CGRect = UIScreen.main.bounds
let screenWidth = screenSize.width
let screenHeight = screenSize.height
//self.view.backgroundColor = UIColor(red: 32/255, green: 32/255, blue: 32/255, alpha: 1.0)
self.view.backgroundColor = UIColor.white
// Navigation View
navView.frame = CGRect(x: 0, y: 0, width: screenSize.width, height: 66)
navView.frame.origin.y = 28
//navLabel.backgroundColor = UIColor(red: 32/255, green: 32/255, blue: 32/255, alpha: 1.0)
navLabel.backgroundColor = UIColor.white
//navView.backgroundColor = UIColor.red.withAlphaComponent(0.5)
self.view.addSubview(navView)
// Navigation Label
self.navView.addSubview(navLabel)
navLabel.frame = CGRect(x: 0, y: 0, width: screenSize.width, height: 66)
navLabel.textAlignment = .center
navLabel.font = UIFont.boldSystemFont(ofSize: 20)
navLabel.textColor = UIColor.black
//navLabel.text = "Workout"
navLabel.text = "Log workout"
navLabel.adjustsFontSizeToFitWidth = true
navLabel.isUserInteractionEnabled = true
self.view.backgroundColor = UIColor.white
configureButtons()
setupFooter()
self.hideKeyboard()
print("Printing ... ... ...")
print(selectedWorkout)
}
func setupFooter() {
let customView = UIView(frame: CGRect(x: 0, y: 0, width: screenSize.width, height: 50))
customView.backgroundColor = UIColor.lightGray
let button = UIButton(frame: CGRect(x: 0, y: 0, width: screenSize.width, height: 50))
button.setTitle("Add Set", for: .normal)
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
customView.addSubview(button)
tableView.tableFooterView = customView
}
@objc func buttonAction(_ sender: UIButton!) { // Add new set/row in tableView
print("Button tapped")
let a = Array(stride(from: 1, through: 50, by: 1)) // Haven't tested yet. Add new set in array
setsArray.append("a")
// Update Table Data
tableView.beginUpdates()
tableView.insertRows(at: [
(NSIndexPath(row: setsArray.count-1, section: 0) as IndexPath)
], with: .automatic)
tableView.endUpdates()
}
func configureButtons() {
confiureCloseButton()
confiureSaveButton()
confiureClearButton()
}
func confiureCloseButton() {
//let button = UIButton(frame: CGRect(x: 100, y: 100, width: 100, height: 50))
let button = UIButton(frame: CGRect(origin: CGPoint.zero, size: menuButtonSize))
button.setImage(UIImage(named: "icon_close"), for: UIControl.State.normal)
button.setImage(UIImage(named: "icon_close")?.alpha(0.5), for: UIControl.State.highlighted)
button.center = CGPoint(x: 50, y: 61)
button.layer.cornerRadius = button.frame.size.width/2
button.layer.zPosition = 1
button.addTarget(self, action: #selector(closeButtonAction), for: .touchUpInside)
button.setTitleColor(.black, for: UIControl.State.normal)
button.backgroundColor = UIColor.red
button.isUserInteractionEnabled = true
self.view.addSubview(button)
}
@objc func closeButtonAction(sender: UIButton!) {
self.dismiss(animated: true, completion: nil)
}
func confiureSaveButton() {
let button = UIButton(frame: CGRect(origin: CGPoint(x: screenSize.width-44-8, y: 28), size: actionButtonSize))
button.setTitle("Save", for: UIControl.State.normal)
//button.backgroundColor = UIColor.blue
button.layer.zPosition = 1
button.addTarget(self, action: #selector(saveButtonAction), for: .touchUpInside)
button.setTitleColor(.black, for: UIControl.State.normal)
button.isUserInteractionEnabled = true
self.view.addSubview(button)
}
@objc func saveButtonAction(sender: UIButton!) {
saveWorkout()
}
func confiureClearButton() {
let button = UIButton(frame: CGRect(origin: CGPoint(x: screenSize.width-44-8-44-8, y: 28), size: actionButtonSize))
button.setTitle("Clear", for: UIControl.State.normal)
//button.backgroundColor = UIColor.red
button.layer.zPosition = 1
button.addTarget(self, action: #selector(clearButtonAction), for: .touchUpInside)
button.isUserInteractionEnabled = true
button.setTitleColor(.black, for: UIControl.State.normal)
self.view.addSubview(button)
}
@objc func clearButtonAction(sender: UIButton!) {
clearWorkout()
}
func clearWorkout() { // Clear workout exercise
print("clear")
}
let nowDate = Date()
var setsArray = [String]()
var previousArray = [String]()
var kgArray = [String]()
var repsArray = [String]()
var notesArray = [String]()
func saveWorkout() { // Save workout exercise
if setsArray.isEmpty {//if !setsArray.isEmpty {
print("Saving workout...")
/*let realm = try! Realm()
let myWorkout = Workout()
myWorkout.date = nowDate
myWorkout.exercise = "Text Exercise"
let aSet0 = Set(numReps: 12, weight: 11.5, aNote: "light workout")
let aSet1 = Set(numReps: 12, weight: 12.5, aNote: "medium workout")
let aSet2 = Set(numReps: 12, weight: 21.0, aNote: "heavy workout")
myWorkout.sets.append(objectsIn: [aSet0, aSet1, aSet2] )
try! realm.write {
realm.add(myWorkout)
print("Saved!")
}*/
} else {
// create the alert
let alert = UIAlertController(title: nil, message: "Please add any exercise before saving!", preferredStyle: UIAlertController.Style.alert)
// add an action (button)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil))
// show the alert
self.present(alert, animated: true, completion: nil)
}
}
// number of rows in table view
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return setsArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ExerciseCreatorCell
let realm = try! Realm()
let getExercises = realm.objects(Workout.self).filter("exercise = 'Text Exercise2'").sorted(byKeyPath: "date",ascending: false)
print(getExercises.last!)
let myWorkout = Workout()
// Find the Workout instance "Bench Press"
let benchPressWorkout = realm.objects(Workout.self).filter("exercise = 'Text Exercise2'").sorted(byKeyPath: "date",ascending: false)
// Access the sets for that instance
let sets = benchPressWorkout[0].sets
for i in sets.indices {
let set0 = sets[i]
// Access reps and kg for set 0
let reps0 = set0.reps
let kg0 = set0.kg
// and so on ...
print([kg0]) // number of KG
print([reps0]) // number of reps
cell.previousTextField.text = "\(kg0) x \(reps0)"
}
cell.setLabel.text = "\(indexPath.row + 1)"
return cell
}
// method to run when table view cell is tapped
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("tapped")
}
}
编辑:正如@rs7 之前建议的那样,我有三个对象:
锻炼.swift:
@objc dynamic var id = 0
@objc dynamic var date: Date?
// List of exercises (to-many relationship)
var exercises = List<Exercise>()
override static func primaryKey() -> String? {
return "id"
}
Exercise.swift
class Exercise: Object {
@objc dynamic var name: String?
// List of sets (to-many relationship)
var sets = List<Set>()
var parentWorkout = LinkingObjects(fromType: Workout.self, property: "exercises")
}
设置.swift
class Set: Object {
@objc dynamic var reps: Int = 0
@objc dynamic var kg: Double = 0.0
@objc dynamic var notes: String?
// Define an inverse relationship to be able to access your parent workout for a particular set (if needed)
var parentExercise = LinkingObjects(fromType: Exercise.self, property: "sets")
convenience init(numReps: Int, weight: Double, aNote: String) {
self.init()
self.reps = numReps
self.kg = weight
self.notes = aNote
}
}
【问题讨论】:
-
不确定这里的问题是什么。您知道如何从 Realm 获取数据并将其输出到控制台。那么...您是在问如何使用 tableViews 吗?如果您不需要实时更新数据,则使用与 tableViews 一起使用的标准做法;创建一个类来保存要显示的数据,从 sets 列表构建类(通过迭代集合),然后将这些类存储在 tableView 数据源数组中。你能澄清一下吗?
-
我同意 Jay 的观点,你能提供更多细节吗?您是否要显示上一次锻炼?换句话说,您的最后一项工作由多个练习之一组成,每个练习将由一组或多组组成 - 我是否正确理解这一点(顺便说一句,请确保您在上一篇文章中查看我的更新答案。您需要有 3 个类,而不是 2)
-
@rs7 - 是的,我正在尝试在 tablview 中显示我之前针对特定练习的数据。所以假设我已经注册了这个练习
Text Exercise2for xx 次,我想从我上次做那个练习时检索所有组的 kg 和 reps,创建这样的东西:i.stack.imgur.com/6tUIL.png(参考我在 SO 中的另一个问题)。 -
我们将您尝试显示的练习称为 selectedExercise(Exercise 类型)。您基本上将您的表格视图的行数设置为 selectedExercise.sets.count + 2。换句话说,这是您的集合数 + 标题的一行 +“添加集”的一行。然后在您的 cellForRowAt 函数中,您可以将表格的第一行和最后一行配置为分别作为标题和“添加集”单元格。 (您可以为此使用保护语句)至于显示集合信息,您将使用 selectedExercise.sets[indexPath.row - 1]
-
您可以通过将 .kg 和 .reps 附加到 selectedExercise.sets[indexPath.row - 1] 来访问 reps 和 kg。如果您需要更详细的答案,您需要向我提供一些代码和一些上下文,我很乐意提供帮助。另外,就像Jay建议的那样,如果您对它感到满意,请接受另一个线程中的答案。