2017-08-28 4 views
0

私はテーブルビューを持っています。セルをクリックすると、データを編集できるページに移動し、セルからすべての情報が渡されます。それから私は "保存"/"削除"をクリックすることができ、変更をポストします/ firebaseからアイテムを削除します。その後、私はテーブルビューに戻り、新たに更新されたfirebaseデータを取得します。以前に開かれたVCのための機能トリガー

問題私は(私は詳細を削除/編集できるページ)の項目を削除する場合は、その後、バックテーブルビューに遷移します

は、その後、別のセルおよび編集をクリックして保存します編集済みの項目を以前に削除した項目として送信します。どのようにこれが可能なのか私には意味をなさない。

調査

私は、異なる細胞を保存、アイテムを削除するアプリを殺し、再開、、その後みました。この場合、エラーは発生しません。これは、ある種のメモリ/メモリリークの問題があるかもしれないと私に信じていますが、私はこの問題を真に解決できるかどうかはわかりません。

誰が、なぜこの奇妙なfunctiを知っています/

import UIKit 
import Firebase 

class EditVC: UIViewController, UIPickerViewDelegate { 

    @IBOutlet weak var scrollView: UIScrollView! 
    @IBOutlet weak var nameTextField: UITextField! 
    @IBOutlet weak var yearTextField: UITextField! 
    @IBOutlet weak var otherTextField: UITextField! 
    @IBOutlet weak var stateTextField: UITextField! 

    // Variables for items's Details 
    var itemID = "" 
    var name = "" 
    var year = "" 
    var other = "" 
    var state = "" 

    let userID = Auth.auth().currentUser!.uid 
    let ref = Database.database().reference() 


    override func viewDidLoad() { 
     super.viewDidLoad() 
     self.hideKeyboardWhenTappedAround() 
     //for shifting textFields when keyboard covers 
     NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name:NSNotification.Name.UIKeyboardWillShow, object: nil) 
     NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name:NSNotification.Name.UIKeyboardWillHide, object: nil) 

     setUpPickers() 

     // Set initial values for TextFields 
     nameTextField.text = name 
     yearTextField.text = year 
     otherTextField.text = other 
     stateTextField.text = state 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 

    ///////////////////////// 
    // Buttons 
    @IBAction func returnButtonPressed(_ sender: Any) { 
     save() 
     performSegue(withIdentifier: "backToTableView", sender: self) 
    } 

    @IBAction func deleteButtonPressed(_ sender: Any) { 
     if itemID != "" { 
      print("removing item") 
      self.ref.child("users").child(userID).child("items").child(itemID).removeValue(); 
     } 
     performSegue(withIdentifier: "backToTableView", sender: self) 
    } 

    @IBAction func doneButton(_ sender: Any) { 
     save() 
     performSegue(withIdentifier: "backToTableView", sender: self) 
    } 
    // End of [Buttons] 
    ///////////////////////// 

    func save() { 
     // Create an items object to post 
     // Get the values from all textfields and set in the object 
     let itemsToPost : [String: Any] = [ 
      "name": nameTextField.text ?? "", 
      "year": yearTextField.text ?? "", 
      "state": stateTextField.text ?? "", 
      "other": otherTextField.text ?? "" 
     ] 
     // if the user is saving a new item (itemID == ""), then create a new ID and set itemID 
     if (itemID == "") { 
      itemID = ref.child("users/" + userID + "/items").childByAutoId().key 
     } 
     // post the items object to firebase 
     for item in items { 
      self.ref.child("users/" + userID + "/items/" + itemID).child(item.key).setValue(item.value) 
     } 
    } 

    ////////// 
    // Picker Controllers 

    //Arrays for picker views 
    let stateArray = ["State", "AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DE", "FL", "GA", "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MD", "MA", "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ", "NM", "NY", "NC", "ND", "OH", "OK", "OR", "PA", "RI", "SC", "SD", "TN", "TX", "UT", "VT", "VA", "WA", "WV", "WI", "WY"] 
    var yearArray : [String] = [] 
    let errorArray = ["unable to load"] 

    let yearPickerView = UIPickerView() 
    let statePickerView = UIPickerView() 

    func setUpPickers() { 
     print("running setUpPickers") 
     // new picker 
     yearPickerView.delegate = self 
     yearTextField.inputView = yearPickerView 
     statePickerView.delegate = self 
     stateTextField.inputView = statePickerView 

     var i = 1900 
     let date = Date() 
     let calendar = Calendar.current 
     let maxYear = calendar.component(.year, from: date) 
     while i < (maxYear + 1) { 
      yearArray.insert(String(describing: i), at: 0) 
      i += 1 
     } 
    } 

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { 
     print("setting titleForRow...") 
     if pickerView == statePickerView { 
      return stateArray[row] 
     } else if pickerView == yearPickerView { 
      return yearArray[row] 
     } else { 
      return errorArray[0] 
     } 
    } 

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { 
     print("setting numberOfRowsInComponent...") 
     if pickerView == statePickerView { 
      return stateArray.count 
     } else if pickerView == yearPickerView { 
      return yearArray.count 
     } else { 
      return errorArray.count 
     } 
    } 

    public func numberOfComponents(in pickerView: UIPickerView) -> Int{ 
     print("setting numberOfComponents...") 
     return 1 
    } 

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { 
     print("setting didSelectRow...") 

     if pickerView == statePickerView { 
      print("setting text of stateTextField") 
      stateTextField.text = stateArray[row] 

      if stateTextField.text == stateArray[0] { 
       stateTextField.textColor = UIColor.lightGray 
      } else { 
       stateTextField.textColor = UIColor.black 
      } 
     } else if pickerView == yearPickerView { 
      print("setting text of yearTextField") 
      yearTextField.text = yearArray[row] 

      if yearTextField.text == stateArray[0] { 
       yearTextField.textColor = UIColor.lightGray 
      } else { 
       yearTextField.textColor = UIColor.black 
      } 
     } 
    } 

    // 
    ////////// 


    /////////////////////////////////////// 
    // shifting text fields (add listeners in viewDidLoad) 
    func keyboardWillShow(notification:NSNotification){ 
     print("running keyboardWillShow...") 
     //give room at the bottom of the scroll view, so it doesn't cover up anything the user needs to tap 
     var userInfo = notification.userInfo! 
     var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue 
     keyboardFrame = self.view.convert(keyboardFrame, from: nil) 

     var contentInset:UIEdgeInsets = self.scrollView.contentInset 
     contentInset.bottom = (keyboardFrame.size.height + 60) 
     self.scrollView.contentInset = contentInset 
    } 

    func keyboardWillHide(notification:NSNotification){ 
     print("running keyboardWillHide...") 
     let contentInset:UIEdgeInsets = UIEdgeInsets.zero 
     self.scrollView.contentInset = contentInset 

     print("saving...") 
     save() 
     print("finished keyboardWillHide...") 
    } 
    // 
    /////////////////////////////////////// 
} 

を削除テーブルビュー編集する

import UIKit 
import Firebase 

class ItemListVC: UIViewController, UITableViewDelegate, UITableViewDataSource, UIPickerViewDelegate { 

    //reference to firebase database 
    var ref : DatabaseReference? 
    var handle : DatabaseHandle? 
    var allItemData : [String:Any] = [:] 
    // Get current userID 
    let userID = (Auth.auth().currentUser?.uid) ?? "" 
    // Outlets 
    @IBOutlet weak var addItemOutlet: UIButton! 
    @IBOutlet weak var tableView: UITableView! 
    @IBOutlet weak var numberOfItemsTextBox: UITextField! 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     // Set up tableView 
     tableView.delegate = self 
     tableView.dataSource = self 
     tableView.rowHeight = 69 
     // Set up UIPickerView (dropdown for numberOfItemsTextBox) 
     setUpPickers() 
    } 

    override func viewDidAppear(_ animated: Bool) { 
     super.viewDidAppear(animated) 
     // fetch user's item data from firebase 
     ref = Database.database().reference() 
     handle = ref?.child("users").child(userID).child("items").observe(DataEventType.value, with: { (snapshot) in 
      // replace the old array 
      self.allItemData = snapshot.value as? [String : AnyObject] ?? [:] 
      // reload the UITableView 
      self.tableView.reloadData() 
      self.setEnableForAddOutlet() 
     }) 
     // Get numberOfItems 
     ref.child("user/" + userID + "/items/numberOfItems").observeSingleEvent(of: .value, with: { (snapshot) in 
      if snapshot.value is NSNull { 
       self.numberOfItemsTextBox.text = "" 
      } else { 
       // successfully fetched value 
       value = (snapshot.value as? NSDictionary)! 
       self.numberOfItemsTextBox.text = numberOfItems 
      } 
     }) 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 

    func save() { 
     print("post the value for numberOfItems to firebase") 
     let itemsToPost : [String: Any] = [ 
      "numberOfItems" : numberOfItemsTextBox.text ?? "", 
     ] 
     for item in items { 
      self.ref.child("users/" + userID + "/items").child(item.key).setValue(item.value) 
     } 
    } 

    // Action when the return key pressed 
    func textFieldShouldReturn(_ textField: UITextField) -> Bool { 
     print("running textFieldShouldReturn") 
     textField.resignFirstResponder() 
     return true 
    } 

    func setEnableForAddOutlet() { 
     if (allItemData.count > 1) { 
      addItemOutlet.isEnabled = false 
     } else { 
      addItemOutlet.isEnabled = true 
     } 
    } 

    //////////////// 
    // BUTTONS 
    @IBAction func addItemButtonPressed(_ sender: Any) { 
     // Save 
     save() 
     performSegue(withIdentifier:"ItemAdd", sender: nil) 
    } 

    @IBAction func nextButtonPressed(_ sender: Any) { 
     // Save 
     save() 
     performSegue(withIdentifier:"mySegueToADifferentPlace", sender: nil) 
    } 

    @IBAction func doneButtonPressed(_ sender: Any) { 
     // Save 
     save() 
     performSegue(withIdentifier:"mySegueToSomeWhereElse", sender: nil) 
    } 

    @IBAction func backButtonPressed(_ sender: Any) { 
     // Save 
     save() 
     performSegue(withIdentifier:"mySegueToSomeWhereElse", sender: nil) 
    } 

    // End of [BUTTONS] 
    //////////////// 

    //////////////// 
    // TABLE VIEW 

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

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
     let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! itemListCell 
     let key = Array(allItemData.keys)[indexPath.row] 
     let item = (allItemData[key] as? [String:Any]) ?? [:] 
     let name = (item["name"] as? String) ?? "" 
     let year = (item["year"] as? String) ?? "" 
     cell.titleLabel?.text = name 
     cell.itemID = key 
     cell.name = name 
     cell.year = year 
     cell.other = (item["other"] as? String) ?? "" 
     cell.state = (item["state"] as? String) ?? "" 

     return cell 
    } 

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){ 
     performSegue(withIdentifier:"ItemEdit", sender: nil) 
    } 

    // End of [TABLE VIEW] 
    //////////////// 


    ////////// 
    // Picker Controllers 


    //Arrays for picker views 
    let numOfItemsArray = ["0", "1", "2", "2+"] 
    let errorArray = ["unable to load"] 

    let itemPickerView = UIPickerView() 

    func setUpPickers() { 
     print("running setUpPickers") 
     // new picker 
     itemPickerView.delegate = self 
     numberOfItemsTextBox.inputView = itemPickerView 
    } 

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { 
     print("setting titleForRow...") 
     if pickerView == itemPickerView { 
      return numOfItemsArray[row] 
     } else { 
      return errorArray[0] 
     } 
    } 

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { 
     print("setting numberOfRowsInComponent...") 
     if pickerView == itemPickerView { 
      return numOfItemsArray.count 
     } else { 
      return errorArray.count 
     } 
    } 

    func numberOfComponents(in pickerView: UIPickerView) -> Int{ 
     print("setting numberOfComponents...") 
     return 1 
    } 

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { 
     print("setting didSelectRow...") 

     if pickerView == itemPickerView { 
      //change the text in the textField equal to the selection 
      let value = numOfItemsArray[row] 
      numberOfItemsTextBox.text = value 
      if value == numOfItemsArray[0] { 
       numberOfItemsTextBox.textColor = UIColor.lightGray 
      } else { 
       numberOfItemsTextBox.textColor = UIColor.black 
      } 
     } 
     numberOfItemsTextBox.resignFirstResponder() 
    } 

    // 
    ////////// 


    /////////////////// 
    //MARK: - Navigation 
    //In a storyboard-based application, you will often want to do a little preparation before navigation 
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 
     if segue.identifier == "ItemEdit" { 
      // get the indexPath of the selected cell 
      if let indexPath = tableView.indexPathForSelectedRow { 
       // get the selected cell 
       let cell = tableView.cellForRow(at: indexPath) as! itemListCell 
       // get an instance of the next ViewController 
       let itemController : EditVC = segue.destination as! EditVC 
       // take all the data from the selected cell and pass it to the next ViewController 
       print("itemController variables") 
       itemController.itemID = cell.itemID 
       itemController.name = cell.name 
       itemController.year = cell.year 
       itemController.other = cell.other 
       itemController.state = cell.state 
      } else { 
       // tell the user if the indexPath of the selected cell cannot be retrieved 
       print("Unable to select item") 
      } 
     } 
    } 
    ////////////////// 
} 

のViewControllerと私の試み

のViewController一貫性が発生しているとどのようにそれを解決するには?

は、任意のアイデア

+0

2番目のviewcontrollerからdeleteButtonPressedからperformSegue(withIdentifier: "backToTableView"、sender:self)という行をコメントしてからコードを実行すると、結果は何ですか? – 3stud1ant3

+0

"backToTableView"のperpareForSegueを作成し、このスペースを使用して、変数に渡されたすべてを ""に戻してください。その後、リロード時に削除された情報がまだ投稿されているかどうかを確認します。 – DoesData

+0

@DoesData、ご提案いただきありがとうございます。それは良い考えだった。私は変数を '' PrepForSegue''を使って ""に戻してみましたが、これは実際にはさらに重複していました。 – Rbar

答えて

0

ソリューションのために事前にありがとう:


推論

機能から save()を削除

他人を助ける場合は、keyboardWillHideメソッドがsave()を呼び出すという問題がありました。 固定キーに保存することを意味する場合は、フィールドの編集が終了するたびにキーボードが非表示になり、データがfirebaseに保存されるため、実際には問題ありません。 しかし、は毎回同じキーではなくユニークキー(itemID)にポストしているので、キーを作成してファイアベースに保存するためのキーの重複呼び出しが生成されます。次に、Table Viewを使用してコントローラに戻り、firebaseに保存された重複値がすべてロードされます。

関連する問題