質問編集履歴

2 画像を追加しました。

grief137

grief137 score 2

2018/11/07 23:41  投稿

【Swift】TableViewのcell削除でHeaderの要素が消えてしまう
Swiftを勉強している初心者です。
UITableViewにRealmSwiftから取得したレコードを表示し、不要なレコードをスワイプで削除する際にしていますが、UITableViewDelegateのviewForHeaderInSectionで表示しているUITableViewCellまで一緒に消えてしまいます。
Headerのcellは削除されず、section内のレコードのみ削除されるようにしたいです。
コードの添削、アドバイスなどをしていただけたら幸いです。
どうぞよろしくお願い致します。
### 該当のソースコード
```ViewController
import UIKit
import RealmSwift
import SlideMenuControllerSwift
class ViewController: UIViewController{
//抜粋
   
   @IBOutlet weak var tableView: UITableView!
   var wordEntities:Results<Words>? = nil
   var category:Category? = nil
   let realm = try! Realm()
   
   override func viewDidLoad() {
       super.viewDidLoad()
       tableView.delegate = self
       tableView.dataSource = self
       setNavigationBarItem()
       setNavigationBarTitle(title: "Words")
       tableView.rowHeight = UITableView.automaticDimension
       tableView.register(UINib(nibName: "WordTableViewCell", bundle: nil), forCellReuseIdentifier: "WordItemCell")
   }
   
   override func viewWillAppear(_ animated: Bool) {
       super.viewWillAppear(animated)
       if category != nil {
           wordEntities = realm.objects(Words.self).filter("categoryId == %@", category!.categoryId).sorted(byKeyPath: "updateDate", ascending: false)
       }else{
           wordEntities = realm.objects(Words.self).sorted(byKeyPath: "updateDate", ascending: false)
       }
       
       if wordEntities != nil{
           tableView.reloadData()
           tableView.reloadSections(NSIndexSet(index: tableView.sectionIndexMinimumDisplayRowCount) as IndexSet, with: .none)
       }
   }
   
//TableView Delegate
extension ViewController: UITableViewDelegate{
   //**********************
   //ここでdelete時にHeaderのcellも一緒に消えてしまう
   //**********************
   func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
       if editingStyle == .delete{
           try! realm.write {
               if let wordEntities = wordEntities{
                   realm.delete(wordEntities[indexPath.row])
               }
           }
       }
       tableView.reloadData()
   }
   
   //display tableview header
   func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
       let headerview = UIView()
       headerview.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 100)
       headerview.backgroundColor = UIColor.white
       
       let searchbar = UISearchBar()
       searchbar.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 50)
       searchbar.placeholder = "検索"
       headerview.addSubview(searchbar)
       
   //**********************
   //TableViewCellをHeaderに表示
   //**********************
       let cell = tableView.dequeueReusableCell(withIdentifier:"WordItemCell") as! WordTableViewCell
       cell.frame = CGRect(x:0, y:55, width:self.view.frame.size.width, height:44)
       cell.delegate = self
       cell.dropdown.dataSource = arrayCategoryList()
       headerview.addSubview(cell)
       
       return headerview
   }
   
   //tableview header height size
   func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat{
       return 100
   }
}
//TableView DataSource
extension ViewController: UITableViewDataSource{
   //display cell count
   func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
       if let wordEntities = wordEntities{
           return wordEntities.count
       }
       return 0
   }
   
   //display cell details
   func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
       let cell = tableView.dequeueReusableCell(withIdentifier:"WordItemCell") as! WordTableViewCell
       cell.delegate = self
       cell.dropdown.dataSource = arrayCategoryList()
       if let wordEntities = wordEntities{
           cell.textfield.text = wordEntities[indexPath.row].word
           cell.wordId = wordEntities[indexPath.row].wordId
           cell.beforeWord = wordEntities[indexPath.row].word
           if wordEntities[indexPath.row].categoryName != nil{
               cell.categorybutton.setTitle(wordEntities[indexPath.row].categoryName, for: .normal)
               cell.categoryName = wordEntities[indexPath.row].categoryName
               cell.beforecategoryName = wordEntities[indexPath.row].categoryName
           }
       }
       return cell
   }
}
```
### 試したこと
delete後にreloadData()だけでなくreloadSections()も加えてみたら、削除1回目はCellも残ったままになりましたが、2回目以降削除すると結局消えてしまいます。
```ViewController
   func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
       if editingStyle == .delete{
           try! realm.write {
               if let wordEntities = wordEntities{
                   realm.delete(wordEntities[indexPath.row])
               }
           }
       }
       //ここを追加
       tableView.reloadSections(NSIndexSet(index: tableView.sectionIndexMinimumDisplayRowCount) as IndexSet, with: .none)
.none)
       tableView.reloadData()
   }
```
### 補足情報(FW/ツールのバージョンなど)
Swift 4.2
Xcode 10.0
RealmSwift 3.11.1
RealmSwift 3.11.1
###スクリーンショット
一番上のTextfieldとButton(ヘッダーに表示しているcellです)が、
![イメージ説明](f74d077a85fb13508ab068fe508a115e.png)
"d"を削除すると、一緒に表示されなくなってしまいます。
(削除するcellの位置に関係なく消えます)
![イメージ説明](14f75757c10dda2ef413cb92c3e316b5.png)
  • Xcode

    5173 questions

    Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

  • Swift

    9181 questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • Realm

    269 questions

    RealmとはSQLiteやCore Dataに代わるモバイルデータベースです。iOSとAndroidの両方でサポートされています。

1 説明文、該当ソースコードの記載を修正しました。

grief137

grief137 score 2

2018/11/05 23:40  投稿

【Swift】TableViewのcell削除でTableHeaderの要素まで消えてしまう
【Swift】TableViewのcell削除でHeaderの要素が消えてしまう
いつもお世話になっております。  
Swiftを勉強している初心者です。
UITableViewにRealmSwiftから取得したレコードを表示し、不要なレコードを削除する際にTableViewDelegateのeditingStyleを利用して実装しております。
UITableViewにRealmSwiftから取得したレコードを表示し、不要なレコードをスワイプで削除する際にしていますが、UITableViewDelegateのviewForHeaderInSectionで表示しているUITableViewCellまで一緒に消えてしまいます。
UITableViewDelegateのviewForHeaderInSectionでHeaderに、UISearchBarとUITableViewCellを表示しております。
しかしレコードをスワイプしてdeleteした際に、Header内のTableViewCellまで削除されてしまいます。
その為Headerのcellは削除されず、section内のレコードのみ削除されるようにしたいです。
Headerのcellは削除されず、section内のレコードのみ削除されるようにしたいです。
コードの添削、アドバイスなどをしていただけたら幸いです。
どうぞよろしくお願い致します。
### 該当のソースコード
```
// WordsListViewController.swift
```ViewController
import UIKit
import RealmSwift
import SlideMenuControllerSwift
class WordsListViewController: UIViewController{
class ViewController: UIViewController{
//抜粋
   
   @IBOutlet weak var tableView: UITableView!
   var wordEntities:Results<Words>? = nil
   var category:Category? = nil
   let realm = try! Realm()
   
   override func viewDidLoad() {
       super.viewDidLoad()
       tableView.delegate = self
       tableView.dataSource = self
       setNavigationBarItem()
       setNavigationBarTitle(title: "Words")
       tableView.rowHeight = UITableView.automaticDimension
       tableView.register(UINib(nibName: "WordTableViewCell", bundle: nil), forCellReuseIdentifier: "WordItemCell")
   }
   
   override func viewWillAppear(_ animated: Bool) {
       super.viewWillAppear(animated)
       if category != nil {
           wordEntities = realm.objects(Words.self).filter("categoryId == %@", category!.categoryId).sorted(byKeyPath: "updateDate", ascending: false)
       }else{
           wordEntities = realm.objects(Words.self).sorted(byKeyPath: "updateDate", ascending: false)
       }
       
       if wordEntities != nil{
           tableView.reloadData()
           tableView.reloadSections(NSIndexSet(index: tableView.sectionIndexMinimumDisplayRowCount) as IndexSet, with: .none)
       }
   }
   
   override func didReceiveMemoryWarning() {  
       super.didReceiveMemoryWarning()  
   }  
     
   func saveWord(Id: String, text: String, category: String){  
       var wordItem:Results<Words>? = nil  
       var item:Words? = nil  
         
       //No Category  
       if !category.isEmpty{  
           wordItem = wordEntities?.filter("wordId == %@", Id)  
           item = wordItem?.first  
       }  
         
       //add Category  
       if item == nil{  
           //insert  
           insertWord(text: text, categoryName: category)  
       }else{  
           //update  
           updateWord(text: text, categoryName: category, wordItem: item!)  
       }  
       tableView.reloadData()  
   }  
     
   //insert new word  
   func insertWord(text: String, categoryName: String){  
       var categoryItem:Results<Category>? = nil  
       var category:Category? = nil  
       let item: [String: Any]  
 
       if !categoryName.isEmpty{  
           categoryItem = findCategoryItem(categoryName: categoryName)  
           category = Category(value: [  
               "categoryId": categoryItem!.first!.categoryId,  
               "categoryName": categoryItem!.first!.categoryName])  
           item = ["word": text,  
               "categoryId": categoryItem!.first!.categoryId,  
               "categoryName": categoryName]  
       }else{  
           item = ["word": text,  
                   "categoryId": 0,  
                   "categoryName": "No Category"]  
       }  
         
       let newWord = Words(value: item)  
         
       try! realm.write(){  
           realm.add(newWord)  
           if category != nil{  
               category?.words.append(newWord)  
               realm.create(Category.self, value: category!, update: true)  
           }  
       }  
   }  
     
   //update word  
   func updateWord(text: String, categoryName: String, wordItem: Words){  
       var categoryItem:Results<Category>? = nil  
       var category:Category? = nil  
       let item: [String: Any]  
         
       categoryItem = findCategoryItem(categoryName: categoryName)  
       if categoryItem?.count != 0{  
           category = Category(value: [  
               "categoryId": categoryItem!.first!.categoryId,  
               "categoryName": categoryItem!.first!.categoryName])  
           item = ["wordId": wordItem.wordId!,  
           "word": text,  
           "updateDate": Date(),  
           "categoryId": categoryItem!.first!.categoryId,  
           "categoryName": categoryItem!.first!.categoryName]  
       }else{  
           item = ["wordId": wordItem.wordId!,  
                   "word": text,  
                   //                                      "userId": "test-user",  
               "categoryName": "No Category",  
               "updateDate": Date()]  
       }  
         
       var oldCategoryItem:Results<Category>? = nil  
       var removeWordItem:Category? = nil  
       var removeWordItemIndex:Int? = nil  
       var oldCategory:Category? = nil  
         
       if wordItem.categoryId != 0{  
           oldCategoryItem = findCategoryItem(categoryName: wordItem.categoryName!)  
           removeWordItem = Array(oldCategoryItem!).first  
           removeWordItemIndex = removeWordItem!.words.index(matching: "wordId == %@", wordItem.wordId!)  
           oldCategory = Category(value: removeWordItem!)  
       }  
         
 
       let editWord = Words(value: item)  
       try! realm.write(){  
           realm.add(editWord, update: true)  
           if category != nil{  
               category!.words.append(editWord)  
               realm.create(Category.self, value: category!, update: true)  
           }  
           if removeWordItemIndex != nil{  
               oldCategory!.words.remove(at: removeWordItemIndex!)  
               realm.create(Category.self, value: oldCategory!, update: true)  
           }  
       }  
   }  
}  
 
//TableView Delegate
extension WordsListViewController: UITableViewDelegate{
   
extension ViewController: UITableViewDelegate{
   //**********************
   //**********************
   func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
       if editingStyle == .delete{
           try! realm.write {
               if let wordEntities = wordEntities{
                   realm.delete(wordEntities[indexPath.row])
               }
           }
       }
       tableView.reloadData()
   }
   
   //display tableview header
   func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
       let headerview = UIView()
       headerview.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 100)
       headerview.backgroundColor = UIColor.white
       
       //まだ張りぼて状態...  
       let searchbar = UISearchBar()
       searchbar.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 50)
       searchbar.placeholder = "検索"
       headerview.addSubview(searchbar)
       
   //**********************
   //該当のTableViewCellの生成箇所
   //TableViewCellをHeaderに表示
   //**********************
       let cell = tableView.dequeueReusableCell(withIdentifier:"WordItemCell") as! WordTableViewCell
       cell.frame = CGRect(x:0, y:55, width:self.view.frame.size.width, height:44)
       cell.delegate = self
       cell.dropdown.dataSource = arrayCategoryList()
       headerview.addSubview(cell)
       
       return headerview
   }
   
   //tableview header height size
   func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat{
       return 100
   }
 
}
//TableView DataSource
extension WordsListViewController: UITableViewDataSource{
extension ViewController: UITableViewDataSource{
   //display cell count
   func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
       if let wordEntities = wordEntities{
           return wordEntities.count
       }
       return 0
   }
   
   //display cell details
   func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
       let cell = tableView.dequeueReusableCell(withIdentifier:"WordItemCell") as! WordTableViewCell
       cell.delegate = self
       cell.dropdown.dataSource = arrayCategoryList()
       if let wordEntities = wordEntities{
           cell.textfield.text = wordEntities[indexPath.row].word
           cell.wordId = wordEntities[indexPath.row].wordId
           cell.beforeWord = wordEntities[indexPath.row].word
           if wordEntities[indexPath.row].categoryName != nil{
               cell.categorybutton.setTitle(wordEntities[indexPath.row].categoryName, for: .normal)
               cell.categoryName = wordEntities[indexPath.row].categoryName
               cell.beforecategoryName = wordEntities[indexPath.row].categoryName
           }
       }
       return cell
   }
}
//Textfield Delegate(extension WordTableViewCell)  
extension WordsListViewController: InputTextTableCellDelegate{  
   //textfield has finished to edit  
   func textFieldDidEndEditing(cell: WordTableViewCell, value: String) -> () {  
       if value != cell.beforeWord || cell.categoryName != cell.beforecategoryName {  
           saveWord(Id: cell.wordId!, text: value, category: cell.categoryName!)  
       }  
   }  
}  
```
### 試したこと
delete後にreloadData()だけでなくreloadSections()も加えてみたら、削除1回目はCellも残った状態になりますが、2回目以降もdeleteすると表示されなくなってしまいます。
delete後にreloadData()だけでなくreloadSections()も加えてみたら、削除1回目はCellも残ったままになりましたが、2回目以降削除すると結局消えてしまいます。
```
```ViewController
   func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
       if editingStyle == .delete{
           try! realm.write {
               if let wordEntities = wordEntities{
                   realm.delete(wordEntities[indexPath.row])
               }
           }
       }
       //ここを追加
       //ここを追加
       tableView.reloadSections(NSIndexSet(index: tableView.sectionIndexMinimumDisplayRowCount) as IndexSet, with: .none)
.none)
       tableView.reloadData()
   }
```
### 補足情報(FW/ツールのバージョンなど)
Swift 4.2
Xcode 10.0
RealmSwift 3.11.1
  • Swift

    9181 questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • Realm

    269 questions

    RealmとはSQLiteやCore Dataに代わるモバイルデータベースです。iOSとAndroidの両方でサポートされています。

  • Xcode

    5173 questions

    Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る