2017-01-21 2 views
0

Я разрабатываю приложение в Swift, и у меня проблема с пользовательскими ячейками. У меня есть одна пользовательская ячейка, и когда вы нажимаете кнопку «Добавить», она создает другую пользовательскую ячейку. Ячейка имеет 3 текстовых поля и 2 кнопки. Эти текстовые поля - это имя, цена и количество ингредиента, который я создаю. Когда я использую только одну пользовательскую ячейку или добавляю еще одну, чтобы сделать ее двумя, данные сохраняются правильно. Но когда я добавляю 2 пользовательских ячейки (всего 3 пользовательских ячеек), у меня есть проблема неправильной цены, только последние два компонента рассчитываются в цене. Когда я добавляю 3 пользовательских ячейки (всего 4 пользовательских ячейки), он только воссоздает первую ячейку с заполненными данными, как в первой ячейке. Нажатие кнопки «Отключить», я получаю фатальную ошибку: Найден нуль при разворачивании Дополнительное значение.Разработка iOS Быстрые пользовательские ячейки

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

Cell

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 строкой. Но если у вас есть 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 ингредиент = ингредиенты [указательPath.строка] в моем консольном выпуске Я получаю: фатальная ошибка: индекс за пределами диапазона – Alen

Смежные вопросы