【问题标题】:Get data from Realm List<>从领域列表<>获取数据
【发布时间】: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 Exercise2 for 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建议的那样,如果您对它感到满意,请接受另一个线程中的答案。

标签: ios swift xcode realm


【解决方案1】:

无论如何我都会给你答案,但不要忘记修复你的代码。

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // number of rows = number of sets (not counting the header row)
    return selectedExercise.sets.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ExerciseCreatorCell
    let currentSet = selectedExercise.sets[indexPath.row]
    cell.setNumberLabel.text = "\(indexPath.row)"
    cell.kgLabel.text = "\(currentSet.kg)"
    cell.repsLabel.text = "\(currentSet.reps)"
    return cell
}

【讨论】:

  • 评论不用于扩展讨论;这个对话是moved to chat
  • 当使用这三个对象时 - 如何在 cellForRow 中显示它们?这个答案基于两个对象(?)当锻炼包含多个对象(锻炼)时,我想在单元格中显示每个锻炼的锻炼名称。 (问题也通过编辑更新)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-25
  • 1970-01-01
相关资源
最近更新 更多