Nano Hash - криптовалюты, майнинг, программирование

Сохранение галочки Bool/tableView - повезло в третий раз

Это третий раз, когда я опубликовал эту проблему, и я еще не получил рабочий ответ.

Итак, у меня есть фитнес-приложение, пользователь выбрал одну тренировку, прежде чем она была отображена в виде таблицы, когда выбрана ячейка, я хочу, чтобы она показывала эту ячейку (содержащую упражнение) как завершенную, пометив ее галочкой. это отлично работает, но я борюсь с тем, как сохранить эту галочку, когда приложение завершается и перезапускается.

Ниже я привел пример одной из моделей тренировки и контроллера табличного представления.

Пожалуйста, может кто-нибудь попробовать и решить эту проблему!!

Спасибо.

Джош

Пример модели тренировки -

import Foundation
class The600Workout {
    var workoutArray = [
        Workout(exercise: "Don't forget to warm up before every workout!", completed: false),
        Workout(exercise: "Start with little/ no weight and work your way up", completed: false),
        Workout(exercise: "------------------------------------------------------------------", completed: false),
        Workout(exercise: "Pull ups | 25 Reps", completed: false),
        Workout(exercise: "Lunges | 50 Reps (Low weight)", completed: false),
        Workout(exercise: "Calf Raises | 50 Reps (Low weight)", completed: false),
        Workout(exercise: "Shoulder press | 50 Reps (Low weight)", completed: false),
        Workout(exercise: "Push ups | 50 Reps", completed: false),
        Workout(exercise: "Shrugs | 50 Reps (Low weight)", completed: false),
        Workout(exercise: "Leg raises | 50 Reps", completed: false),
        Workout(exercise: "Bench press | 50 Reps (Low weight)", completed: false),
        Workout(exercise: "More Pull ups | 25 Reps", completed: false),
        Workout(exercise: "Squats | 50 Reps (Low weight)", completed: false),
        Workout(exercise: "Incline Bench press | 50 Reps (Low weight)", completed: false),
        Workout(exercise: "Bicep curls | 50 Reps (Low weight)", completed: false),
        Workout(exercise: "Tricep pull downs | 50 Reps (Low weight)", completed: false),
    ]
}

Контроллер табличного представления

import UIKit
class workoutTableView: UIViewController, UITableViewDataSource, UITableViewDelegate {
    @IBOutlet weak var workoutTableView: UITableView!
    var navTitle: String = ""
    var workout = [Workout]()
    let tlabel = UILabel()
    override func viewDidLoad() {
        super.viewDidLoad()
        setWorkout()
        workoutTableView.delegate = self
        workoutTableView.dataSource = self
        tlabel.text = navTitle
        tlabel.textAlignment = .center
        tlabel.font = UIFont(name: "Arial Rounded MT Bold", size: 30)
        tlabel.adjustsFontSizeToFitWidth = true
        navigationItem.titleView = tlabel
    }
    func setWorkout() {
        if navTitle == "The 600 Workout" {
            workout = The600Workout().workoutArray
        }
        else if navTitle == "5 Days for Muscle" {
            workout = FiveDaysForMuscle().workoutArray
        }
        else if navTitle == "Marathon Ready" {
            workout = MarathonReady().workoutArray
        }
        else if navTitle == "HIIT @ Home" {
            workout = HIITAtHome().workoutArray
        }
        else if navTitle == "Get Strong" {
            workout = GetStrong().workoutArray
        }
        else if navTitle == "Body Weight Blast" {
            workout = BodyWeightBlast().workoutArray
        }
        else if navTitle == "Bands Pump" {
          workout = BandsPump().workoutArray
        }
        else if navTitle == "Quickie Warm up" {
            workout = QuickieWarmUp().workoutArray
        }
        else if navTitle == "The Best Circuit Workout" {
            workout = TheBestCircuit().workoutArray
        }
        else if navTitle == "The Gym HIIT Workout" {

            workout = GymHIIT().workoutArray
        }
        else if navTitle == "The Ultimate Workout" {
            workout = UltimateWorkout().workoutArray
        }
        else if navTitle == "Warm up For Weights" {
            workout = WarmUpForWeights().workoutArray
        }
        else if navTitle == "6 Day Bro Split" {
          workout = SixDayBroSplit().workoutArray
        }
        else if navTitle == "Explosive Workout" {
            workout = ExplosiveWorkout().workoutArray
        }
        else if navTitle == "Strength Circuit" {
            workout = StrengthCircuit().workoutArray
        }
        else if navTitle == "Killer Circuit" {    
            workout = KillerCircuit().workoutArray
        }
        else if navTitle == "Fitness Test" {
            workout = FitnessTest().workoutArray
        }
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return workout.count
    }
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        workout[indexPath.row].completed = !workout[indexPath.row].completed
        tableView.cellForRow(at: indexPath)?.accessoryType = workout[indexPath.row].completed ?  .checkmark : .none
        tableView.deselectRow(at: indexPath, animated: false)
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "prototypeCell", for: indexPath)
        cell.textLabel?.text = workout[indexPath.row].exercise
        cell.accessoryType = workout[indexPath.row].completed ?  .checkmark : .none
        cell.layer.borderWidth = 5
        cell.layer.cornerRadius = 20
        cell.layer.borderColor = #colorLiteral(red: 0, green: 0.3285208941, blue: 0.5748849511, alpha: 1)
        cell.textLabel?.textColor = UIColor.black
        cell.textLabel?.adjustsFontSizeToFitWidth = true
        cell.textLabel?.font = .boldSystemFont(ofSize: 15)
        return cell   
    }
}

Ответы:


1

Сохранить текущее состояние ячейки (выбрано или нет) в UserDefault. После перезапуска выберите ячейку автоматически в соответствии с данными UserDefaults. Например:

var selectedCell = 0 // For declaration

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        workout[indexPath.row].completed = !workout[indexPath.row].completed
        tableView.cellForRow(at: indexPath)?.accessoryType = workout[indexPath.row].completed ?  .checkmark : .none
        tableView.deselectRow(at: indexPath, animated: false)

        self.selectedCell = indexPath.row 
        UserDefaults.standart.set(self.selectedCell, forKey: "selectedCellIndex")
    }

И в ячейкеForRowAt:

if indexPath.row == UserDefaults.standart.object(forKey: selectedCellIndex){
//select this cell and whatever you want
} else {
//Other cells 
}

Надеюсь, поможет...

20.01.2020

2

Чтобы иметь возможность сохранять состояние completed каждого упражнения отдельно, вам необходимо провести рефакторинг модели данных.

  • Создайте файл JSON для всей модели — например, с именем WorkoutData.json — и поместите его в пакет приложения. Файл содержит все тренировки и связанные с ними упражнения и будет скопирован в папку Documents при первом запуске или если вы планируете функцию сброса. Структура файла JSON такова.

    [{"name":"The600Workout","exercises":
        [{"title":"Don't forget to warm up before every workout!", "completed": false},
        {"title":"Start with little/ no weight and work your way up", "completed": false},
        {"title":"------------------------------------------------------------------", "completed": false},
        {"title":"Pull ups | 25 Reps", "completed": false},
        {"title":"Lunges | 50 Reps (Low weight)", "completed": false},
        {"title":"Calf Raises | 50 Reps (Low weight)", "completed": false},
        {"title":"Shoulder press | 50 Reps (Low weight)", "completed": false},
        {"title":"Push ups | 50 Reps", "completed": false},
        {"title":"Shrugs | 50 Reps (Low weight)", "completed": false},
        {"title":"Leg raises | 50 Reps", "completed": false},
        {"title":"Bench press | 50 Reps (Low weight)", "completed": false},
        {"title":"More Pull ups | 25 Reps", "completed": false},
        {"title":"Squats | 50 Reps (Low weight)", "completed": false},
        {"title":"Incline Bench press | 50 Reps (Low weight)", "completed": false},
        {"title":"Bicep curls | 50 Reps (Low weight)", "completed": false},
        {"title":"Tricep pull downs | 50 Reps (Low weight)", "completed": false}]
    },
    {"name":"5 Days for Muscle","exercises": [ ... ]},
    {"name": ... [ ... ]},
    ...         
    ] 
    
  • Создайте две структуры, соответствующие Codable, которые соответствуют данным JSON.

    struct Exercise : Codable {
        let title : String
        var completed : Bool
    }
    
    struct Workout : Codable {
        let name : String
        let exercises : [Exercise]
    }
    
  • В viewDidLoad получить URL-адрес файла в папке Documents с вычисляемым свойством

    var workoutDataURL : URL {
            return try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent("WorkoutData.json")
    }
    

    и проверьте, существует ли файл. Если нет, скопируйте файл из пакета в Documents.

  • Создайте два метода для загрузки и сохранения данных с помощью JSONDecoder/JSONEncoder
  • Вызовите метод load в viewDidLoad и перезагрузите табличное представление.
  • Вызывайте метод save всякий раз, когда пользователь выбирает ячейку для изменения состояния completed.
  • Вместо бесконечного выражения if - else if вы можете просто получить тренировку с помощью workout = workoutArray.first{$0.name == navTitle}!
  • Удалить все классы тренировок. Они больше не нужны.

Это довольно простое решение. Более эффективным решением является использование такой базы данных, как Core data. Преимущество заключается в том, что вам не нужно хранить всю модель данных в памяти.

20.01.2020
  • Как мне создать файл JSON и хранить в нем модели? Спасибо 20.01.2020
  • Есть два способа: 1) Используйте текстовый редактор и создайте JSON (который представляет собой обычный текст) с помощью функции «Найти и заменить» (как я быстро сделал в своем примере). 2) Создайте массив ваших классов в коде и закодируйте массив с помощью JSONEncoder. Оба способа просты и понятны. 20.01.2020
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..