質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Realm

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

Xcode

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

Swift

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

Q&A

解決済

1回答

899閲覧

【Swift】TableViewのcell削除でHeaderの要素が消えてしまう

grief137

総合スコア14

Realm

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

Xcode

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

Swift

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

1グッド

0クリップ

投稿2018/11/04 06:10

編集2018/11/07 14:41

Swiftを勉強している初心者です。

UITableViewにRealmSwiftから取得したレコードを表示し、不要なレコードをスワイプで削除する際にしていますが、UITableViewDelegateのviewForHeaderInSectionで表示しているUITableViewCellまで一緒に消えてしまいます。

Headerのcellは削除されず、section内のレコードのみ削除されるようにしたいです。

コードの添削、アドバイスなどをしていただけたら幸いです。
どうぞよろしくお願い致します。

該当のソースコード

ViewController

1 2import UIKit 3import RealmSwift 4import SlideMenuControllerSwift 5 6class ViewController: UIViewController{ 7//抜粋 8 9 @IBOutlet weak var tableView: UITableView! 10 var wordEntities:Results<Words>? = nil 11 var category:Category? = nil 12 13 let realm = try! Realm() 14 15 override func viewDidLoad() { 16 super.viewDidLoad() 17 tableView.delegate = self 18 tableView.dataSource = self 19 setNavigationBarItem() 20 setNavigationBarTitle(title: "Words") 21 tableView.rowHeight = UITableView.automaticDimension 22 tableView.register(UINib(nibName: "WordTableViewCell", bundle: nil), forCellReuseIdentifier: "WordItemCell") 23 } 24 25 override func viewWillAppear(_ animated: Bool) { 26 super.viewWillAppear(animated) 27 if category != nil { 28 wordEntities = realm.objects(Words.self).filter("categoryId == %@", category!.categoryId).sorted(byKeyPath: "updateDate", ascending: false) 29 }else{ 30 wordEntities = realm.objects(Words.self).sorted(byKeyPath: "updateDate", ascending: false) 31 } 32 33 if wordEntities != nil{ 34 tableView.reloadData() 35 tableView.reloadSections(NSIndexSet(index: tableView.sectionIndexMinimumDisplayRowCount) as IndexSet, with: .none) 36 } 37 } 38 39//TableView Delegate 40extension ViewController: UITableViewDelegate{ 41 //********************** 42 //ここでdelete時にHeaderのcellも一緒に消えてしまう 43 //********************** 44 func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { 45 if editingStyle == .delete{ 46 try! realm.write { 47 if let wordEntities = wordEntities{ 48 realm.delete(wordEntities[indexPath.row]) 49 } 50 } 51 } 52 tableView.reloadData() 53 } 54 55 //display tableview header 56 func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { 57 let headerview = UIView() 58 headerview.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 100) 59 headerview.backgroundColor = UIColor.white 60 61 let searchbar = UISearchBar() 62 searchbar.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 50) 63 searchbar.placeholder = "検索" 64 headerview.addSubview(searchbar) 65 66 //********************** 67 //TableViewCellをHeaderに表示 68 //********************** 69 let cell = tableView.dequeueReusableCell(withIdentifier:"WordItemCell") as! WordTableViewCell 70 cell.frame = CGRect(x:0, y:55, width:self.view.frame.size.width, height:44) 71 cell.delegate = self 72 cell.dropdown.dataSource = arrayCategoryList() 73 headerview.addSubview(cell) 74 75 return headerview 76 } 77 78 //tableview header height size 79 func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat{ 80 return 100 81 } 82} 83 84//TableView DataSource 85extension ViewController: UITableViewDataSource{ 86 //display cell count 87 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 88 if let wordEntities = wordEntities{ 89 return wordEntities.count 90 } 91 return 0 92 } 93 94 //display cell details 95 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 96 let cell = tableView.dequeueReusableCell(withIdentifier:"WordItemCell") as! WordTableViewCell 97 cell.delegate = self 98 cell.dropdown.dataSource = arrayCategoryList() 99 100 if let wordEntities = wordEntities{ 101 cell.textfield.text = wordEntities[indexPath.row].word 102 cell.wordId = wordEntities[indexPath.row].wordId 103 cell.beforeWord = wordEntities[indexPath.row].word 104 105 if wordEntities[indexPath.row].categoryName != nil{ 106 cell.categorybutton.setTitle(wordEntities[indexPath.row].categoryName, for: .normal) 107 cell.categoryName = wordEntities[indexPath.row].categoryName 108 cell.beforecategoryName = wordEntities[indexPath.row].categoryName 109 } 110 } 111 return cell 112 } 113} 114 115

試したこと

delete後にreloadData()だけでなくreloadSections()も加えてみたら、削除1回目はCellも残ったままになりましたが、2回目以降削除すると結局消えてしまいます。

ViewController

1 func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { 2 if editingStyle == .delete{ 3 try! realm.write { 4 if let wordEntities = wordEntities{ 5 realm.delete(wordEntities[indexPath.row]) 6 } 7 } 8 } 9 //ここを追加 10 tableView.reloadSections(NSIndexSet(index: tableView.sectionIndexMinimumDisplayRowCount) as IndexSet, with: .none) 11.none) 12 tableView.reloadData() 13 }

補足情報(FW/ツールのバージョンなど)

Swift 4.2
Xcode 10.0
RealmSwift 3.11.1

###スクリーンショット
一番上のTextfieldとButton(ヘッダーに表示しているcellです)が、
イメージ説明

"d"を削除すると、一緒に表示されなくなってしまいます。
(削除するcellの位置に関係なく消えます)
イメージ説明

fuzzball👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

UITableViewCellをセクションに使うのがどうにも気持ち悪いので、使わない方向で考えてみました。

現在は、WordTableViewCell(カスタムセル)をセルとセクションで共有していますが、これを、

  • 共有部分はカスタムビュー(UIView)にする。
  • セルは、このカスタムビューをセルに乗せる。
  • セクションは、このカスタムビューをそのまま使う。

という風にしてみてはどうでしょうか?

役に立たなかった回答

Headerの要素が消えてしまうことに関係しているかどうかは分かりませんが、削除時にwordEntitiesが更新されてないです。

投稿2018/11/06 06:42

編集2018/11/09 00:22
fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

grief137

2018/11/07 00:21

ご回答ありがとうございます。 RealmのResultオブジェクトは逐一更新されるため、データに変更があっても毎回取得する必要がない想定です。 (参考元:)https://qiita.com/noppefoxwolf/items/92eae2789564cba073cc 削除後にもwordEntitiesを再度取得するようにしてみましたが、特に挙動は変わりませんでした。
fuzzball

2018/11/07 00:38

なるほど、失礼しました。
fuzzball

2018/11/07 00:43

じっくり見る時間がないので、ぱっと見て申し訳ないですが、気になったことだけ書いておきます。 ・セルの生成に dequeueReusableCell(withIdentifier:for:) ではなく dequeueReusableCell(withIdentifier:) が使われている。 ・セクションにUITableViewCellを使っている。(こういうコードは見たことがないです)
grief137

2018/11/07 14:31

>・セルの生成に dequeueReusableCell(withIdentifier:for:) ではなくdequeueReusableCell(withIdentifier:) が使われている。 ご指摘の通り、cellForRowAtでの生成時にdequeueReusableCell(withIdentifier:for:) を使うようにしました。 しかしviewForHeaderInSectionではfor:の引数のIndexPathでコンパイルが解決できなかった為、今の所そのままにしています。 >・セクションにUITableViewCellを使っている。(こういうコードは見たことがないです) ViewController内でレコードの登録・更新を完結させたくて、レコードの表示と同じ入力欄に統一するべくヘッダーにもnibファイルで作ったcellを再利用するようにしてました。 (ヘッダーの位置もTableを上にスワイプした時に固定したかったです) 一覧に出しているUIと同じレイアウトで表示できるなら特に方法は問いません。
fuzzball

2018/11/07 16:11

ちょっと書き方を間違えました。 セクションにUITableViewCellを使っていること自体は問題無いと思いますが、 dequeueReusableCell()を使って生成しているのが不味いかも知れません。dequeueReusableCell()を使わずに、普通にインスタンスを生成するようにするとどうなるでしょうか? その前に、セクションにセルを使わず普通のものにして、正しい動作になるかどうか確認した方がいいかも知れません。(問題の切り分けのため)
grief137

2018/11/08 14:14

セルの代わりに別のUIを表示して削除を行ったところ、ヘッダーの情報が消えることはありませんでした。 ご指摘の通り、dequeueReusableCell()を使っていたことが原因のようです。 ただ、セルのインスタンス生成はまだうまくいっておりません。 現在以下のように生成しようとしていますが、cast出来なくて怒られてしまいます。 ``` let cell = UITableViewCell(style: WordTableViewCell.CellStyle.default, reuseIdentifier: "WordItemCell") as! WordTableViewCell ``` "Could not cast value of type 'UITableViewCell' (0x10a0988e0) to 'WordTableViewCell'" nibファイルの再利用でdequeueReusableCell()以外の生成方法を知らない為、もし根本的に考え違うようであればアドバイス頂きたいです。
fuzzball

2018/11/09 00:23

ちょっと回答を更新してみました。 (23:14のコメントに対する回答ではありません)
grief137

2018/11/09 03:27

回答の更新ありがとうございます。 まだ試せていないのですが、確認させてください。 以下のイメージで合っていますでしょうか。(勉強不足で理解しきれていないかもしれないので) 【回答での提案内容】 ・カスタムビュー⇒UIView.addSubView(WordTableViewCell) TableView ・セクション⇒カスタムビュー ・セル⇒UITableViewCell.addSubView(カスタムビュー)
fuzzball

2018/11/09 03:55 編集

>>・カスタムビュー⇒UIView.addSubView(WordTableViewCell) 現在の WordTableViewCell をそのまま使う、という意味でしたら違います。 UITableViewCellは使わず、UIViewをベースにして別のカスタムビューを作ります。(例えば WordTableView という名前で) >>・セクション⇒カスタムビュー >>・セル⇒UITableViewCell.addSubView(カスタムビュー) こちらは合っていると思います。 ただし、UITableViewCell に直接 addSubView するのではなく、UITableViewCell.contentView にaddSubViewして下さい。
grief137

2018/11/09 04:43

ご回答ありがとうございます。 WordTableViewCellをそのまま使う想定でした。 UIViewベースで作り直す必要があるのですね。 検証次第、ご報告いたします。
grief137

2018/11/10 06:44

検証できました! そしてセルを削除してもセクションも消えなくなり、解消できました。 最後まで本当にありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問