2016-10-30 14 views
0

値:The proper way to delete rows from UITableView and update array from NSUserDefaults in Swift/iOSSwift3:テーブルビューでのエラー削除の細胞がUserDefaultを保持している私はここに提供されるすべての手順に従っ

しかし、誤差が言って、発生しています。

「無効な更新:更新後の既存のセクションに含まれるセクション0の行の無効数 行の数が(2) 前に、そのセクションに含まれる行の数に等しくなければなりません(0が挿入され、1が削除された) から挿入または削除された行の数をプラスまたはマイナスし、そのセクションに出入りする行の数をプラスまたはマイナスします。 )。

Iは

クラスTableViewController作成した別のコントローラからのUITableViewController {

struct Section { 
    var sectionName: String! 
    var words: [String]! 

    init(title: String, word: [String]) { 
     self.sectionName = title 
     self.words = word 

    } 
} 

var arrayForRows = [String]() 

var sections = [Section]() 
func getData() -> [String] { 
if let data = userDefaultDataSave.stringArray(forKey: "data") { 
    return data 
} 
return [] 
} 
override func viewDidLoad() { 
    super.viewDidLoad() 

    tableView.dataSource = self 

    guard let data = dataDefaults.stringArray(forKey: "data") else { 
     return 
    } 
    arrayForRows = data as [String] 
    tableView.reloadData() 

    sections = [ 
     Section(title: "A", word: []), // 1 
     Section(title: "B", word: []), //2 
     Section(title: "C", word: []), 
     Section(title: "D", word: []), 
     Section(title: "E", word: []), 
     Section(title: "F", word: []), 
     Section(title: "G", word: []), 
     Section(title: "H", word: []), 
     Section(title: "I", word: []), 
     Section(title: "J", word: []), 
     Section(title: "K", word: []), 
     Section(title: "L", word: []), 
     Section(title: "M", word: []), 
     Section(title: "N", word: []), 
     Section(title: "O", word: []), 
     Section(title: "P", word: []), 
     Section(title: "Q", word: []), 
     Section(title: "R", word: []), 
     Section(title: "S", word: []), 
     Section(title: "T", word: []), 
     Section(title: "U", word: []), 
     Section(title: "V", word: []), 
     Section(title: "W", word: []), 
     Section(title: "X", word: []), 
     Section(title: "Y", word: []), 
     Section(title: "Z", word: []) 
    ] 


    let getAlphabetData = getData() 

    for a in getAlphabetData { 

     if a.hasPrefix("A") || a.hasPrefix("a") { 
      if sections[0].sectionName == "A" { 
       sections[0].words.append(a as String) 
      } 
     } 

     if a.hasPrefix("B") || a.hasPrefix("b") { 
      if sections[1].sectionName == "B" { 
       sections[1].words.append(a as String) 
      } 
     } 

     if a.hasPrefix("c") || a.hasPrefix("c") { 
      if sections[2].sectionName == "C" { 
       sections[2].words.append(a as String) 
      } 
     } 
     if a.hasPrefix("D") || a.hasPrefix("d") { 
      if sections[3].sectionName == "D" { 
       sections[3].words.append(a as String) 
      } 
     } 
     if a.hasPrefix("E") || a.hasPrefix("e") { 
      if sections[4].sectionName == "E" { 
       sections[4].words.append(a as String) 
      } 
     } 
     if a.hasPrefix("F") || a.hasPrefix("f") { 
      if sections[5].sectionName == "F" { 
       sections[5].words.append(a as String) 
      } 
     } 
     if a.hasPrefix("G") || a.hasPrefix("g") { 
      if sections[6].sectionName == "G" { 
       sections[6].words.append(a as String) 
      } 
     } 
     if a.hasPrefix("H") || a.hasPrefix("h") { 
      if sections[7].sectionName == "H" { 
       sections[7].words.append(a as String) 
      } 
     } 
     if a.hasPrefix("I") || a.hasPrefix("i") { 
      if sections[8].sectionName == "I" { 
       sections[8].words.append(a as String) 
      } 
     } 
     if a.hasPrefix("J") || a.hasPrefix("j") { 
      if sections[9].sectionName == "J" { 
       sections[9].words.append(a as String) 
      } 
     } 
     if a.hasPrefix("K") || a.hasPrefix("k") { 
      if sections[10].sectionName == "K" { 
       sections[10].words.append(a as String) 
      } 
     } 
     if a.hasPrefix("L") || a.hasPrefix("l") { 
      if sections[11].sectionName == "L" { 
       sections[11].words.append(a as String) 
      } 
     } 
     if a.hasPrefix("M") || a.hasPrefix("m") { 
      if sections[12].sectionName == "M" { 
       sections[12].words.append(a as String) 
      } 
     } 
     if a.hasPrefix("N") || a.hasPrefix("n") { 
      if sections[13].sectionName == "N" { 
       sections[13].words.append(a as String) 
      } 
     } 
     if a.hasPrefix("O") || a.hasPrefix("o") { 
      if sections[14].sectionName == "O" { 
       sections[14].words.append(a as String) 
      } 
     } 
     if a.hasPrefix("P") || a.hasPrefix("p") { 
      if sections[15].sectionName == "P" { 
       sections[15].words.append(a as String) 
      } 
     } 
     if a.hasPrefix("Q") || a.hasPrefix("q") { 
      if sections[16].sectionName == "Q" { 
       sections[16].words.append(a as String) 
      } 
     } 
     if a.hasPrefix("R") || a.hasPrefix("r") { 
      if sections[17].sectionName == "R" { 
       sections[17].words.append(a as String) 
      } 
     } 
     if a.hasPrefix("S") || a.hasPrefix("s") { 
      if sections[18].sectionName == "S" { 
       sections[18].words.append(a as String) 
      } 
     } 
     if a.hasPrefix("T") || a.hasPrefix("t") { 
      if sections[19].sectionName == "T" { 
       sections[19].words.append(a as String) 
      } 
     } 
     if a.hasPrefix("U") || a.hasPrefix("u") { 
      if sections[20].sectionName == "U" { 
       sections[20].words.append(a as String) 
      } 
     } 
     if a.hasPrefix("V") || a.hasPrefix("v") { 
      if sections[21].sectionName == "V" { 
       sections[21].words.append(a as String) 
      } 
     } 
     if a.hasPrefix("W") || a.hasPrefix("w") { 
      if sections[22].sectionName == "W" { 
       sections[22].words.append(a as String) 
      } 
     } 
     if a.hasPrefix("X") || a.hasPrefix("x") { 
      if sections[23].sectionName == "X" { 
       sections[23].words.append(a as String) 
      } 
     } 
     if a.hasPrefix("Y") || a.hasPrefix("y") { 
      if sections[24].sectionName == "Y" { 
       sections[24].words.append(a as String) 
      } 
     } 
     if a.hasPrefix("Z") || a.hasPrefix("z") { 
      if sections[25].sectionName == "Z" { 
       sections[25].words.append(a as String) 
      } 
     } 
    } 

} 

// MARK: - Table view data source 

override func numberOfSections(in tableView: UITableView) -> Int { 
    // #warning Incomplete implementation, return the number of sections 
    return sections.count 
} 

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 
    return 50.0 
} 

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    // #warning Incomplete implementation, return the number of rows 

    return arrayForRows.count 
} 


override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 
    return sections[section].sectionName 
} 



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

    // Cellに値を設定する. 
    cell.textLabel?.font = UIFont.systemFont(ofSize: 20) 
    cell.textLabel?.textColor = UIColor.black 

    cell.textLabel!.text = sections[indexPath.section].words[indexPath.row] 

    return cell 
} 

// Override to support editing the table view. 
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { 

    if editingStyle == .delete { 
     // Delete the row from the data source 

     tableView.beginUpdates() 

     arrayForRows.remove(at: indexPath.row) 
     self.tableView.deleteRows(at: [indexPath], with: .automatic) 

     let userDefaults = UserDefaults.standard 
     userDefaults.set(arrayForRows, forKey: "data") 
     tableView.endUpdates() 
    } else if editingStyle == .insert { 
     // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view 
    } 

} 

}

を、値は、この方法を書き込むことによって、セクションのwords配列に追加されます。

class InputDataViewController: UIViewController { 


// this function is written inside UITextView in this class. 
//But I omitted here. 

func addData(text: String) { 

    var data = self.getData() 
    data.insert(text as NSString, at: 0) 
    dataDefault.set(data, forKey: "data") 
} 


func getData() -> [String] { 
    if let data = dataDefault.stringArray(forKey: "data") { 
     return data 
    } 
    return [] 
} 

} 

何が問題ですか?私がそれを見る方法から、私がtableView.reloadData()またはtableView.beginUpdates()endUpdates()を明示的に書いていないかどうかを理解できます。このエラーの原因は何ですか?私たちを手伝ってくれますか?

ありがとうございました。また

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    // #warning Incomplete implementation, return the number of rows 
    return sections[section].words.count 
} 

を更新しました

は、私はこのように書いた場合、それが働いていたことが分かりました。ただし、選択したものは私のテーブルビューから削除されませんでした。セクションの行を選択して削除したにもかかわらず、最初の単語インデックスがテーブルビューから削除されました。削除された行は別のセクションにあります。

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { 

    if editingStyle == .delete { 
     // Delete the row from the data source 
     //   removeHistory(index: sections[indexPath.section].words[indexPath.row]) 

     tableView.beginUpdates() 

     let indexSet = NSMutableIndexSet() 
     indexSet.add(indexPath.section) 


     //let indexSet = sections[indexPath.section].words[indexPath.row] as IndexSet 
     //sections.remove(at: indexPath.section) 
     sections[indexPath.section].words.remove(at: indexPath.row) 
     var data = getData() 
     data.remove(at: indexPath.row) 
     dataDefault.set(data, forKey: "data") 
     dataDefault.synchronize() 

     //tableView.deleteSections(indexSet, with: UITableViewRowAnimation.fade) 
     tableView.deleteRows(at: [indexPath], with: .fade) 

     tableView.endUpdates() 
     // 



    } else if editingStyle == .insert { 
     // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view 
    } 
} 
+0

** reloadData' 'への呼び出し**後?スニペットに 'tableView:numberOfRowsInSection:'の実装を含めると役に立ちます。 – crizzis

+0

@crizzis更新を確認してください – Ryo

答えて

0

多分、問題は、データを削除する前にテーブルビューから行を削除することですか?あなたの配列からオブジェクトを削除しようとすると、tableViewから行を削除してください

tableView.beginUpdates() 
    arrayForRows.remove(at: indexPath.row) 
    self.tableView.deleteRows(at: [indexPath], with: .automatic) 
    let userDefaults = UserDefaults.standard 
    userDefaults.set(arrayForRows, forKey: "data") 
    tableView.endUpdates() 

numberOfRowsInSectionメソッドも見てみてください。私はそれが返されるはずです

arrayForRows.count 
+0

いいえ、動作しません。私もこれを試しましたが、失敗しました。私は解決策を探しています...コードに問題はありませんが、バグがあります。 – Ryo

+0

@Ryoは、私が提案した方法でnumberOfRowsInSectionを変更しようとしています。問題はarrayForRowsからデータを削除することですが、テーブルビューの行数はこの配列に依存しません – valivaxa

+0

そして、今度は「インデックスが範囲外です」 – Ryo

1

行を追加または削除するたびに、データソースが一貫していることを確認する必要があります。あなたのケースでは、オブジェクトのフロンarrayForRowsを削除しているが、あなたのnumberOfRowsは完全に異なるデータソース使用されています。だから、あなたはどちらか

  1. そのままnumberOfRowsをキープし、sections[indexPath.section].words配列
  2. 変更から削除する必要がありますsections[section].words.count

    をあなたのnubmerOfRows返す方法arrayForRows.count

あなたのデータソースとは何ですか彼は正しいオプションです。複数のセクションがあるので、最初の提案に従ってください。

編集:あなたがあなたのsections配列を更新しないようなので

あなたはindex out of boundsエラーを取得しています。すべてのセクションのすべてのそれらのwordsの配列を記入する必要がありますか?しかし、あなたが提供したコードで判断すると、それらは常に空です。

  1. のViewController Aは、すべてのセクション
  2. のViewController Bに特定の文字から始まる単語を持つセクションのリストを表示する新しい要素を作成し、UserDefaultsに保存:

    基本的にはあなたの実装は次のようになります。

  3. viewWillAppearメソッドでVC Aは毎回sectionsアレイを更新する必要があります。 UserDefaultsから配列内のすべての要素をループして、すべての要素を右のSectionオブジェクトに入れてください。
  4. VC Aで行が削除されるたびに、に対応するセクションオブジェクトから削除する必要があります。それ以外の場合は、アプリケーションがクラッシュします。また、これらの変更を永続的に保つために、UserDefaults配列から同じオブジェクトを削除する必要があります。

あなたsections配列に単語を挿入する関数の例:あなたは、テーブルビューのデータソースを設定しているのはなぜ

func insert(word: String) { 
    guard word.characters.count > 0 else { return } 
    let firstLetter = String(describing: word.characters.first).lowercased() 
    for var section in sections { 
     if section.title.lowercased().hasPrefix(firstLetter) { 
      section.words.append(word) 
     } 
    } 
} 
+0

ありがとうございますが、エラーは "範囲外のインデックス"です。 – Ryo

+0

オブジェクトを削除したり、 'numberOfRows'で削除した場合は? – alexburtnik

+0

更新されたコードを表示して、間違いが何であるか教えてください。 – alexburtnik

関連する問題