2017-01-21 3 views
0

Ich entwickle eine App in Swift und ich habe ein Problem mit benutzerdefinierten Zellen. Ich habe eine benutzerdefinierte Zelle und wenn Sie auf Hinzufügen klicken, wird eine weitere benutzerdefinierte Zelle erstellt. Zelle hat 3 Textfelder und 2 Knöpfe. Diese Textfelder sind Name, Preis und Menge des Inhaltsstoffes der Mahlzeit, die ich erstelle. Wenn ich nur eine benutzerdefinierte Zelle verwende oder eine weitere Zelle hinzufüge, werden die Daten ordnungsgemäß gespeichert. Aber wenn ich 2 benutzerdefinierte Zelle (3 benutzerdefinierte Zellen insgesamt) hinzufügen, habe ich das Problem des falschen Preises, nur die letzten beiden Zutaten werden im Preis berechnet. Wenn ich 3 benutzerdefinierte Zellen (insgesamt 4 benutzerdefinierte Zellen) hinzufüge, erstellt es nur die erste Zelle mit aufgefüllten Daten wie in der ersten Zelle. Am Ende Knopf tippen, bekomme ich einen fatalen Fehler: Fand Null beim Entpacken Optionaler Wert.iOS Entwicklung Schnelle benutzerdefinierte Zellen

View Controller

import UIKit 
import CoreData 

class AddMealViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate { 

    @IBOutlet weak var mealNameTF: UITextField! 

    @IBOutlet weak var addMealsCell: UITableViewCell! 
    @IBOutlet weak var finishButton: UIButton! 
    @IBOutlet weak var resetButton: UIButton! 
    @IBOutlet weak var addButton: UIButton! 
    @IBOutlet weak var addMealTableView: UITableView! 

    @IBOutlet weak var productPrice: UILabel! 
    let currency = "$" // this should be determined from settings 
    var priceTotal = "0" 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     addMealTableView.delegate = self 
     addMealTableView.dataSource = self 
     borderToTextfield(textField: mealNameTF) 
     mealNameTF.delegate = self 
    } 

    func textFieldShouldReturn(_ textField: UITextField) -> Bool { 
      self.view.endEditing(true) 
      return true; 
     } 

    } 

    func numberOfSections(in tableView: UITableView) -> Int { 
     return counter 
    } 

    var counter = 1 

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

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

     borderToTextfield(textField: (cell.amountTF)!) 
     borderToTextfield(textField: (cell.ingredientNameTF)!) 
     //borderToTextfield(textField: cell.normativeTF) 
     borderToTextfield(textField: (cell.priceTF)!) 



     return cell 

    } 


    @IBAction func addButton(_ sender: UIButton) { 
     counter += 1 

     addMealTableView.register(AddMealsTableViewCell.self, forCellReuseIdentifier: "addMealsCell") 
     addMealTableView.reloadData() 

    } 



    @IBAction func resetButton(_ sender: UIButton) { 
     mealNameTF.text = "" 
     for c in 0..<counter{ 
      let indexPath = IndexPath(row: c, section:0) 
      let cell = addMealTableView.cellForRow(at: indexPath) as! AddMealsTableViewCell 
      cell.amountTF.text = "" 
      cell.ingredientNameTF.text = "" 
      // cell.normativeTF.text = "" 
      cell.priceTF.text = "" 
     } 
     productPrice.text = "\(currency)0.00" 
     priceTotal = "0" 
     counter = 1 
    } 

    @IBAction func finishButton(_ sender: UIButton) { 
     for c in (0..<counter){ 
      if let cell = addMealTableView.cellForRow(at: IndexPath(row: c, section: 0)) as? AddMealsTableViewCell { 
       cell.amountTF.delegate = self 
       cell.ingredientNameTF.delegate = self 
       // cell.normativeTF.delegate = self 
       cell.priceTF.delegate = self 

       guard cell.priceTF.text?.isEmpty == false && cell.amountTF.text?.isEmpty == false && mealNameTF.text?.isEmpty == false && cell.ingredientNameTF.text?.isEmpty == false 
        else { 
         return 
       } 

       if cell.priceTF.text?.isEmpty == false{ 
       // if (true) { 
        let tfp = Double((cell.priceTF.text!))!*Double((cell.amountTF.text!))! 
        var ttp = Double(priceTotal) 
        ttp! += tfp 
        priceTotal = String(ttp!) 
       // } 
        }} 
      } 


     let appDelegate = UIApplication.shared.delegate as! AppDelegate 
     let context = appDelegate.persistentContainer.viewContext 
     let newMeal = NSEntityDescription.insertNewObject(forEntityName: "Meal", into: context) 
     let mealName = mealNameTF.text 
     newMeal.setValue(mealName, forKey: "name") 
     newMeal.setValue(priceTotal, forKey: "price") 
     do { 
      try context.save() 

      print("Spremljeno") 
     } catch { 
      print("Neki error") 
     } 

     productPrice.text = currency + priceTotal 
    } 

    @IBAction func addNewIngredientButton(_ sender: UIButton) { 


    } 
    func borderToTextfield(textField: UITextField){ 
     let border = CALayer() 
     let width = CGFloat(2.0) 
     border.borderColor = UIColor.white.cgColor 
     border.frame = CGRect(x: 0, y: textField.frame.size.height - width, width: textField.frame.size.width, height: textField.frame.size.height) 

     border.borderWidth = width 
     textField.layer.addSublayer(border) 
     textField.layer.masksToBounds = true 
     textField.tintColor = UIColor.white 
     textField.textColor = UIColor.white 
     textField.textAlignment = .center 

    } 

    func textFieldShouldReturn(_ textField: UITextField) -> Bool { 
     self.view.endEditing(true) 
     return true; 
    } 
} 

Handy

class AddMealsTableViewCell: UITableViewCell, UITextFieldDelegate{ 

    @IBOutlet weak var DropMenuButton: DropMenuButton! 
    @IBOutlet weak var addNewIngredient: UIButton! 
    @IBOutlet weak var ingredientNameTF: UITextField! 

    // @IBOutlet weak var normativeTF: UITextField! 

    @IBOutlet weak var amountTF: UITextField! 

    @IBOutlet weak var priceTF: UITextField! 

    func textFieldShouldReturn(_ textField: UITextField) -> Bool { 
     self.endEditing(true) 
     return true; 
    } 

    override func prepareForReuse() { 
     self.amountTF.text = "" 
     self.priceTF.text = "" 
     self.ingredientNameTF.text = "" 
    } 

    @IBAction func DropMenuButton(_ sender: DropMenuButton) { 
     DropMenuButton.initMenu(["kg", "litre", "1/pcs"], actions: [({() -> (Void) in 
      print("kg") 
      sender.titleLabel?.text = "kg" 
     }), ({() -> (Void) in 
      print("litre") 

      sender.titleLabel?.text = "litre" 
     }), ({() -> (Void) in 
      print("1/pcs") 
      sender.titleLabel?.text = "1/pcs" 
     })]) 
    } 

    @IBAction func addNewIngredient(_ sender: UIButton) { 


     let name = ingredientNameTF.text 
     let amount = amountTF.text 
     let price = priceTF.text 
     // let normative = normativeTF.text 

     let appDelegate = UIApplication.shared.delegate as! AppDelegate 
     let context = appDelegate.persistentContainer.viewContext 
     let newIngredient = NSEntityDescription.insertNewObject(forEntityName: "Ingredient", into: context) 

     newIngredient.setValue(name, forKey: "name") 
     // newIngredient.setValue(normative, forKey: "normative") 
     newIngredient.setValue(amount, forKey: "amount") 
     newIngredient.setValue(price, forKey: "price") 

     do { 

      try context.save() 
      print("Spremljeno") 
     } catch { 
      print("Neki error") 
     } 
    } 
} 

Antwort

0

Ihr Code sehr schwer zu lesen, aber ich vermute, dass das Problem hier sein kann:

func numberOfSections(in tableView: UITableView) -> Int { 
    return counter 
} 

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

Sie die Rückkehr sind gleiche Anzahl von Zeilen für die Abschnitte und Zeilen für Abschnitte. Also, wenn Sie 1 Zutat haben, sagen Sie, dass es 1 Abschnitt mit 1 Reihe gibt. Aber wenn Sie 2 Zutaten haben, sagen Sie, es gibt 2 Abschnitte mit jeweils 2 Zellen (insgesamt 4 Zellen).

Es gibt viele andere Dinge mit Ihrem Code zu beheben, sind hier ein paar:

Die größte Sache ist, dass Sie diese sehr schwierig machen mit der counter Variable, die Sie haben. Wenn Sie stattdessen eine Reihe von Zutaten haben

var ingredients = [Ingredient]() 

Sie können das verwenden, um alles für die Zählung Ihrer Tabelle einzurichten. Etwas wie folgt aus:

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

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

    let ingredient = ingredients[indexPath.row] 

    cell.ingredientNameTF.text = ingredient.name 
    cell.normativeTF.text = ingredient.normative 
    cell.amountTF.text = ingredient.amount 
    cell.priceTF.text = ingredient.price 

    return cell 
} 

Alle diese können in Interface Builder eingestellt werden (Sie nicht Code-Zeilen in Ihrer Ansicht müssen für sie haben Last):

addMealTableView.delegate = self 
    addMealTableView.dataSource = self 
    mealNameTF.delegate = self 

Diese Zeile in Ihrem viewDidLoad sein sollte Funktion, müssen Sie nur die Klasse einmal registrieren, Sie tun es jedes Mal, wenn Hinzufügen gedrückt wird.

addMealTableView.register(AddMealsTableViewCell.self, forCellReuseIdentifier: "addMealsCell") 

Ihre Aktionsnamen Aktionen

@IBAction func addButtonPressed(_ sender: UIButton) 
@IBAction func resetButtonPressed(_ sender: UIButton) 
@IBAction func finishButtonPressed(_ sender: UIButton) 

Thanks. Now when that ViewController loads I have no cells. My array is now empty so I have to implement some code to addButton which creates another cell and reloads tableView. How can I do that?

Sie brauchen nur eine neue Zutat Objekt an den Zutaten Array hinzufügen und laden die Daten der Tabellenansicht werden sollte.

@IBAction func addButtonPressed(_ sender: UIButton) { 
    let newIngredient = Ingredient() 
    ingredients.append(newIngredient) 
    tableView.reloadData() 
} 
+0

Ok, danke. Aber wenn ich das tue, erscheint ein anderes Problem. Wenn ich die Tabellenansicht dort lade, wo diese benutzerdefinierte Zelle ist, schlägt sie fehl und es heißt: Index außerhalb des Bereichs. Was kann ich tun, um das Problem zu beheben? – Alen

+0

@Alen Welche Zeile schlägt speziell mit diesem Fehler fehl? – ColdLogic

+0

@CodeLogic Bei dieser Zeile: lassen Sie Zutat = Zutaten [indexPath.Zeile] in meiner Konsole Ausgabe bekomme ich: fataler Fehler: Index außerhalb des Bereichs – Alen

Verwandte Themen