2017-01-21 8 views
0

私はSwiftでアプリケーションを開発しており、カスタムセルに問題があります。カスタムセルが1つあり、[追加]ボタンをクリックすると別のカスタムセルが作成されます。セルには3つのテキストフィールドと2つのボタンがあります。それらのテキストフィールドは名前、価格、私が作成している食事の成分の量です。カスタムセルを1つだけ使用する場合、またはカスタムセルを2つ追加する場合は、データが正しく格納されます。しかし、2つのカスタムセル(合計3つのカスタムセル)を追加すると、間違った価格の問題があり、最後の2つの成分のみが価格で計算されます。 3つのカスタムセル(合計4つのカスタムセル)を追加すると、最初のセルのようにデータが挿入された最初のセルのみが再作成されます。 終了ボタンをタップすると、致命的なエラーが表示されます。iOS開発スウィフトカスタムセル

ビューコントローラ

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; 
    } 
} 

セル

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") 
     } 
    } 
} 

答えて

0

あなたのコードは非常に読みにくいですが、私は問題がここにあり疑う:あなたが戻っている

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

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

セクションのセクションと行の両方に同じ行数。 1つの成分がある場合、1つのセクションに1つの行があると言っています。しかし、2つの成分がある場合は、2つのセクションがあり、それぞれに2つのセル(合計4つのセル)があると言っています。

はあなたのコードを修正するための他の多くのものがあり、ここではいくつかある:

最大のものは、あなたが持っているcounter変数で、この非常に困難になっているということです。あなたの代わりに、材料の配列を持っている場合

var ingredients = [Ingredient]() 

あなたはテーブルのカウントのためにすべてを設定することができます。このような何か:

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 
} 

これらのすべては、(あなたのビューでのコードの行を必要といけない彼らのために負荷をした)インタフェースビルダで設定することができます。

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

この行は、あなたのviewDidLoadにする必要があります関数を使用するには、クラスを一度登録するだけで済みます。追加を押すたびにクラスを登録します。

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

あなたのアクション名は、あなただけの食材アレイに新しい成分オブジェクトを追加し、テーブルビューのデータをリロードする必要のあるアクション

@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?

でなければなりません。

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

ありがとう、ありがとう。しかし私がそれをすると、別の問題が現れます。そのカスタムセルがある テーブルビューを読み込むと失敗し、インデックスが範囲外です。 これを解決するにはどうすればよいですか? – Alen

+0

@Alenそのエラーで特に失敗している行は何ですか? – ColdLogic

+0

@CodeLogicこの行の場合: let ingredients = ingredients [indexPath。私のコンソール出力の 私は得る:致命的なエラー:インデックスの範囲外 – Alen