前提・実現したいこと
現在Swiftの練習のためにGoogleKeepを参考にアプリを制作しています。
textFieldが空の時に、バックスペースが入力されたかを判定したいと考えています。
最終的には、空の時にバックスペースが入力されたらcellを削除するという機能にしたいです。
発生している問題・エラーメッセージ
textFieldが空文字だとバックスペースを押しても何も起きない
(shouldChangeCharactersInが呼び出されない)
該当のソースコード
Swift
1// 2// ViewController.swift 3// GoogleKeepTest 4// 5// 6 7import UIKit 8import Firebase 9 10class ViewController: UIViewController { 11 12 @IBOutlet weak var tableView: UITableView! 13 14 var todoList:[String] = [] // TodoListを格納する配列 15 var currentCellIndex = 0 // 現在のセルの添字を代入する 16 17 18 // MARK: View Did Load 19 override func viewDidLoad() { 20 super.viewDidLoad() 21 22 setTableView() // TableViewのdelegateなどの設定を行う 23 } 24 25 26 /// Firestoreにlistを保存する 27 func saveItemData() { 28 Firestore.firestore().collection("TodoCollection").document().updateData(["todoList": todoList]) { (error) in 29 if error != nil { 30 print("\n\nerror内容: (error as Any)") 31 } else { 32 print("## データの保存に成功") 33 print("list: (self.todoList)") 34 self.tableView.reloadData() 35 } 36 } 37 } 38 39} 40 41 42 43 44 45 46// MARK: ProtocolExtension 47extension ViewController: UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate { 48 49 50 51 // MARK: TableView 52 53 /// tableViewのdelegateなどの設定をする 54 func setTableView() { 55 tableView.delegate = self 56 tableView.dataSource = self 57 tableView.register(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: "cell") // 入力欄用のカスタムセル 58 tableView.register(UINib(nibName: "AddCustomCell", bundle: nil), forCellReuseIdentifier: "AddCell") // 追加ボタン用のカスタムセル 59 } 60 61 62 /// アイテムの数を返す 63 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 64 return self.todoList.count + 1 // listの要素数 + 追加ボタン用のカスタムセル 65 } 66 67 68 /// セルが選択された時 69 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 70 // 追加ボタンが押された場合 71 if indexPath.row == todoList.count { 72 // listに空の要素を追加する 73 currentCellIndex = todoList.count 74 todoList.append("") 75 saveItemData() 76 } 77 78 // セルがタップされても背景を白に戻す 79 tableView.deselectRow(at: indexPath, animated: true) 80 } 81 82 83 /// セルの高さを返す 84 func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 85 return CGFloat(40) 86 } 87 88 89 /// cellを生成して返す 90 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 91 92 // 通常の場合(入力用のセル) 93 let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomCell 94 cell.todoLbl.text = todoList[indexPath.row] 95 cell.todoLbl.delegate = self 96 cell.todoLbl.tag = indexPath.row 97 98 // cellの数がlistの要素数に達したら 99 if indexPath.row == todoList.count { 100 // 追加ボタン用のセルを生成する(画像だと「+ リストアイテム」と書いてあるもの。 セルじゃなくてもよいかも?) 101 let addCell = tableView.dequeueReusableCell(withIdentifier: "AddCell", for: indexPath) 102 return addCell 103 } 104 105 // 入力中 or 追加されたセルにフォーカス 106 if currentCellIndex == indexPath.row { 107 cell.todoLbl.becomeFirstResponder() // フォーカスする 108 } 109 110 return cell 111 } 112 113 114 115 116 117 // MARK: UITextField 118 119 120 /// returnが押された時 121 func textFieldShouldReturn(_ textField: UITextField) -> Bool { 122 currentCellIndex = textField.tag + 1 // 入力中セルの添字に+1する 123 todoList.insert("", at: currentCellIndex) // 空の要素を追加する 124 saveItemData() // Firestoreに保存 125 126 return true 127 } 128 129 130 131 /// 1文字入力されるたびに呼ばれる 132 func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { 133 134 // MARK: ここで、バックスペースが押された時にセルを削除する機能を作成しようとした(空文字の時はこのメソッドが呼び出されない) 135 print("\n\n\n=========== Should Change Char ==========") 136 print("list: (todoList)") // listを表示 137 currentCellIndex = textField.tag // 入力中の添字を代入 138 139 140 if let char = string.cString(using: String.Encoding.utf8) { 141 let isBackSpace = strcmp(char, "\b") 142 143 // 入力された文字がバックスペースか否か 144 if (isBackSpace == -92) { 145 print("\\ バックスペースが入力された") 146 // 末尾の1文字を削除 147 todoList[currentCellIndex] = String(todoList[currentCellIndex].dropLast()) 148 } else { 149 print("\\ 文字が入力された: (string) ") 150 todoList[currentCellIndex] = textField.text! + string 151 } 152 } 153 154 saveItemData() 155 currentCellIndex = textField.tag 156 return true 157 } 158 159} 160 161
試したこと
- ゼロ幅スペースをセルに初期値として置く
-> やり方がわからなかった
2. 全てのセルに初期値としてスペースを入れておく(スペースが削除されたらセルを削除する方式)
-> 一瞬だけスペースが削除されるアニメーションが起きるため適切ではないと考えた
3. 入力された文字を取得して、バックスペースの時に処理をする方法を調べた
-> よくわからなかった
補足情報(FW/ツールのバージョンなど)
Swift 5.3
Xcode 12.0.1
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/10/08 12:51
2020/10/08 13:07
2020/10/08 14:36