Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
820 views
in Technique[技术] by (71.8m points)

swift - unable to save on/off state of a UITableViewCell?

there are two attributes 'time' and 'isOn' (string, bool) in the entity named 'Item'

in viewcontroller class I am able to give default condition to 'isOn' attribute (in savePressed function) which makes switchbtn.isOn = true and saves it in the data model for that particular 'time'

viewcontroller class :-

class ViewController: UIViewController {

    let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

    @IBOutlet weak var timePickerView: UIDatePicker!

    @IBOutlet weak var timeLbl: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        timePickerView.setValue(UIColor.white, forKeyPath: "textColor")
        dateFormat()

        // Do any additional setup after loading the view.
    }

    @IBAction func savePressed(_ sender: UIBarButtonItem) {
        let entity = Item(context: context)
        entity.time = timeLbl.text
        entity.isOn = true
        saveData()
        self.dismiss(animated: true, completion: nil)
    }

    @IBAction func cancelPressed(_ sender: UIBarButtonItem) {

        self.dismiss(animated: true, completion: nil)

    }

    @IBAction func valueChanged(sender:UIDatePicker, forEvent event: UIEvent){
        dateFormat()
    }

    func saveData() {
        (UIApplication.shared.delegate as! AppDelegate).saveContext()
    }

    func dateFormat() {
        let formatter = DateFormatter()
        formatter.dateFormat = "HH:mm"
        formatter.timeStyle = .short
        timeLbl.text = formatter.string(from: timePickerView.date)
    }

}

viewcontroller

in this class I am able to fetch and show the core data but don't know how to save the state of the cell switch button and update the data model as there is no use of 'didSelectRowAt' function

tableview class :-

class TableViewController: UITableViewController {

    let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

    var items = [Item]()

    override func viewDidLoad() {
        super.viewDidLoad()
        print(arr)
    }

    override func viewWillAppear(_ animated: Bool) {
        getData()
        tableView.reloadData()
    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {

        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return items.count
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) as! TableViewCell

        cell.timeLbl.text = items[indexPath.row].time
        cell.switchBtn.isOn = items[indexPath.row].isOn

        return cell
    }

    func getData() {
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        do {
             items = try context.fetch(Item.fetchRequest())
        }catch{
            print("failed to get the data")
        }

    }

}

tableview

in this I am able to print the current state of the switch but cannot access the 'items[indexPath.row]' from the tableview class

cell class :-

class TableViewCell: UITableViewCell {

    @IBOutlet weak var timeLbl: UILabel!

    @IBOutlet weak var switchBtn: UISwitch!

    var alarm = Bool()

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

    @IBAction func valChange(_ sender: UISwitch) {
        if sender.isOn{
            switchBtn.isOn = true
        }else {
            switchBtn.isOn = false
        }
    }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

In Swift the most efficient way is a callback closure.

In the cell add a property callback with a closure passing a Bool value and no return value. Call the callback when the value of the switch changed.

class TableViewCell: UITableViewCell {

    @IBOutlet weak var timeLbl: UILabel!
    @IBOutlet weak var switchBtn: UISwitch!

    var alarm = Bool()

    var callback : ((Bool) -> Void)?

    @IBAction func valChange(_ sender: UISwitch) {
        callback?(sender.isOn)
    }
}

In cellForRow in the controller add the callback, in the closure update the model.

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) as! TableViewCell

    let item = items[indexPath.row]
    cell.timeLbl.text = item.time
    cell.switchBtn.isOn = item.isOn

    cell.callback = { newValue in
        self.items[indexPath.row].isOn = newValue
    }

    return cell
}

If cells can be inserted, deleted or moved you have to pass also the cell to get the actual index path

class TableViewCell: UITableViewCell {

    @IBOutlet weak var timeLbl: UILabel!
    @IBOutlet weak var switchBtn: UISwitch!

    var alarm = Bool()

    var callback : ((UITableViewCell, Bool) -> Void)?

    @IBAction func valChange(_ sender: UISwitch) {
        callback?(self, sender.isOn)
    }
}

and

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) as! TableViewCell

    let item = items[indexPath.row]
    cell.timeLbl.text = item.time
    cell.switchBtn.isOn = item.isOn

    cell.callback = { currentCell, newValue in
        let currentIndexPath = tableView.indexPath(for: currentCell)!
        self.items[currentIndexPath.row].isOn = newValue
    }

    return cell
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...