2017-06-22 2 views
0

** Ich bin kein guter englischer Sprecher. Bitte vergib mir mein peinliches Englisch.Wie speichern Sie den Status des Kontrollkästchens in Core-Daten in Swift?

Ich arbeite an einem Aufgabenliste-Projekt mit Kontrollkästchen. Ich kann keine Möglichkeit finden, den Status des Kontrollkästchens zu den Kerndaten zu speichern.

Dies ist ein Teil des Codes, den ich gerade verwende. Tasks ist die Entität (Klassendefinition) und hat isMarked als boolesches Attribut. (schneide ich eine Menge machen es einfach so, wenn Sie etwas seltsam im Code finden Sie einen Kommentar schreiben)

import UIKit 
import CoreData 

var toDolist: [Tasks] = [] 

class FirstViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{ 


    override func viewDidLoad() { 
     super.viewDidLoad() 
     self.view.addSubview(toDoTable) 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
    } 

    @IBOutlet weak var toDoTable: UITableView! 

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{ 
     return toDolist.count 
    } 

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{ 
     let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! CustomTableViewCell 
     cell.box.setImage(#imageLiteral(resourceName: "uncheckedbox"), for: .normal) 

     let task = toDolist[indexPath.row] 

     return cell 
    } 

    func getData(){ 
     let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext 
     do{ 
      toDolist = try context.fetch(Tasks.fetchRequest()) 
     }catch{ 
      print("fetching failed") 
     } 
    } 

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

} 


class CustomTableViewCell: UITableViewCell { 
    override func awakeFromNib() { 
     super.awakeFromNib() 
    } 
    override func setSelected(_ selected: Bool, animated: Bool) { 
     super.setSelected(selected, animated: animated) 
    } 
    @IBOutlet weak var box: CheckBox! 
    @IBOutlet weak var taskLbl: UILabel! 
} 

class CheckBox{ 
    var isChecked: Bool = false{ 
     didSet{ 
      if isChecked == true{ 
       self.setImage(#imageLiteral(resourceName: "checkedbox"), for: .normal) 
      }else{ 
       self.setImage(#imageLiteral(resourceName: "uncheckedbox"), for: .normal) 
      } 
     } 
    } 

    override func awakeFromNib(){ 
     self.addTarget(self, action: #selector(self.buttonClicked(_:)), for: .touchUpInside) 
     self.isChecked = false 
    } 

    func buttonClicked(_ sender: UIButton){ 
     if sender == self{ 
      if isChecked == true{ 
       isChecked = false 
      }else{ 
       isChecked = true 
      } 
     } 
    } 
} 

Wie kann ich dieses Problem lösen, indem Sie einige Code, um es hinzuzufügen? Oder muss ich den obigen Code ändern?

+0

Sie müssen zuweisen verbinden (durch Referenzen) das Datenmodell - die 'Task'-Instanzen - zum Zustand und der Aktion der Schaltfläche. Am einfachsten ist es, eine 'Task' -Instanz in' cellForRow' an die benutzerdefinierte Tabellenansichtszelle zu übergeben. Aufgrund der Referenzsemantik bleiben alle Änderungen bestehen und Sie müssen nur den Kontext des verwalteten Objekts speichern. Tatsächlich ist die Unterklassenbildung von UIButton Overkill. – vadian

+0

@vadian Ich habe die Unterklasse 'UIButton' gelöscht, aber wie kann ich eine Instanz 'Tasks' in 'cellForRow' (meinst du 'cellForRowAt'?) An die benutzerdefinierte Tabellenansichtszelle übergeben? Meinst du, ich muss Manuell/None anstelle von Klassendefinition wählen? Entschuldigung, aber ich bin nur ein Anfänger in Programmierung und Englisch .... – chris17

+0

• Fügen Sie eine Eigenschaft 'var task: Tasks!' In die Zelle und fügen Sie eine Zeile 'cell.task = task' in' cellForRowAt' hinzu. Jetzt haben Sie das Datenquellenelement an die Zelle übergeben. • Fügen Sie den "didSet" -Observer zu "task" hinzu, um 'isChecked' auf den aktuellen Wert zu setzen. • Fügen Sie in der Zelle eine IBAction hinzu, um die Berührung zu empfangen und sie in Interface Builder zu verbinden. • Aktualisieren Sie in der Aktion toggle 'isChecked' das Bild und die Eigenschaft in' task'. • Speichern Sie den Kontext. – vadian

Antwort

0

Einfache Lösung:

  • die Unterklasse von UIButton entfernen und die Klasse der Schaltfläche UIButton zurück.
  • In Interface Builder ordnen Sie die Bilder checkedbox und der Schaltfläche für die Zustände selected und default zu. Die Bilder werden abhängig von der Eigenschaft isSelected der Schaltfläche automatisch angezeigt. Das vermeidet vollständig, die Bilder in Code zu aktualisieren.

  • Die Klasse CustomTableViewCell bekam die Eigenschaft task und die IBAction, die Touch Up Inside der Taste verbunden werden müssen. Die Eigenschaft isSelected des task muss mit dem Namen des Attributs des

    NSManagedObject geändert werden
    class CustomTableViewCell: UITableViewCell { 
    
        @IBOutlet weak var box: UIButton! 
        @IBOutlet weak var taskLbl: UILabel! 
    
        var task : Tasks! { 
         didSet { 
          box.isSelected = task.isSelected 
          taskLbl.text = // update the label 
         } 
        } 
    
        @IBAction func buttonClicked(_ sender: UIButton) 
        { 
         let selected = !sender.isSelected 
         sender.isSelected = selected 
         task.isSelected = selected 
         // save the context if needed 
        } 
    
    } 
    
  • In cellForRowAt nur die Zeile die task

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{ 
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! CustomTableViewCell 
        let task = toDolist[indexPath.row] 
        cell.task = task 
        return cell 
    } 
    
+0

Eigentlich hat die Entität 'Tasks'' isMarked' als Attribute, aber abgesehen davon funktionierte es perfekt! Ich danke dir sehr.(Tut mir leid, aber ich kann das nicht abstimmen, weil mir der Ruf fehlt oder so etwas ...) – chris17

Verwandte Themen