サーチバーで検索

テーブルビューのリストの中から任意の文字列を検索できる「SearchBar」について

TODOリストアプリが完成してるのが前提なので見てない人は以下記事参照↓

完成形はこちら

SearchBarに検索したい文字を入力するとテーブルビューの表示が変わります

Main.storyboardの編集

SearchBarを画面上部に配置するだけです。

ViewController.swiftの編集

コード全文です


import UIKit

class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
    
    @IBOutlet weak var addTextView: UITextView!
    @IBOutlet weak var button: UIButton!
    @IBOutlet weak var todoTableView: UITableView!
    @IBOutlet weak var baseView: UIView!
    //サーチバーをひも付け
    @IBOutlet weak var searchField: UISearchBar!
    
    //ユーザーデフォルトのインスタンス宣言
    let userDefaults = UserDefaults.standard
    //chatsという名前の空の配列
    var chats:[String] = []
    
    //SearchBar用に空の変数を準備 下の2つ
    var searchResults:[String] = []
    var isSearching = false
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        //    searchField.enablesReturnKeyAutomatically = false
        //tableviewの線を消す
        todoTableView.tableFooterView = UIView()
        //これ書くと、最下部のextensionとつながる
        addTextView.delegate = self
        
        //起動時はボタンを押せないようにしておく
        button.isEnabled = false
        button.setTitleColor(UIColor.systemGray , for: .normal)
        
        //キーボード入力処理を受け取るコマンド "showKeyboard"
        NotificationCenter.default.addObserver(self, selector: #selector(showKeyboard), name: UIResponder.keyboardWillShowNotification, object: nil)
        //キーボードを隠す処理を受け取るコマンド "hideKeyboart"
        NotificationCenter.default.addObserver(self, selector: #selector(hideKeyboard), name: UIResponder.keyboardWillHideNotification, object: nil)
        
        //キーボードを下に引っ張って消すやつ これはなかなか重要
        let swipDownGesture = UISwipeGestureRecognizer(target: self, action: #selector(dismissKeyboard))
        swipDownGesture.direction = .down
        self.view.addGestureRecognizer(swipDownGesture)
        
        //アプリ起動時にtableViewを読み込む
        todoTableView.register(UINib(nibName: "TableViewCell", bundle: nil), forCellReuseIdentifier: "CustomCell")
        
        //起動時にユーザーデフォルトを呼び出す
        if let arryTodoList = userDefaults.array(forKey: "todoList") as? [String] {
            chats.append(contentsOf: arryTodoList)
        }
        
    }
    
    //cell高さを可変にする もしcellにtextviewを使用してる場合"scrolling Enable"のチェックを外すこと!
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        todoTableView.estimatedRowHeight = 50
        return UITableView.automaticDimension
    }
    
    //セルの個数を指定
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        
        if isSearching == true {
            return searchResults.count
        } else {
            return chats.count
        }
    }
    //セルはTableViewCellから情報取ってくる
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! TableViewCell
        if isSearching {
            cell.textView.text = searchResults[indexPath.row]
        } else {
            cell.textView.text = chats[indexPath.row]
        }
        return cell
    }
    
    //cellを削除するやつ
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            chats.remove(at: indexPath.row)
            todoTableView.deleteRows(at: [indexPath], with: .fade)
            userDefaults.set(chats, forKey: "todoList")
            
        }
    }
    
    
    //キーボードを消すやつ
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.view.endEditing(true)
    }
    
    //キーボードを表示するときに画面をずらす動作 UIViewを指定すると上手く動く
    @objc func showKeyboard(notification: Notification) {
        
        let keyboardFrame = (notification.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as AnyObject).cgRectValue
        
        guard let keyboardMinY = keyboardFrame?.minY else{ return }
        let MaxY = baseView.frame.maxY
        let distance = MaxY - keyboardMinY + 200  // + 100  //この"10"が画面タテ方向への移動量
        let transform = CGAffineTransform(translationX: 0, y: -distance)
        
        UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: []
                       , animations: {
            self.view.transform = transform})
        
    }
    
    //キーボード消える時に画面の位置を元に戻す動作
    @objc func hideKeyboard() {
        UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: []
                       , animations: {
            self.view.transform = .identity})
    }
    
    
    //buttonを押した時の動作
    @IBAction func button(_ sender: Any) {
        
        if searchField.text == "" {
            self.chats.insert(addTextView.text!, at: 0)
            self.todoTableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: UITableView.RowAnimation.right)
            
            //ユーザーデフォルトに保存
            self.userDefaults.set(self.chats, forKey: "todoList")
            //TextViewに空文字を入れて空白にする
            self.addTextView.text = ""
            //keyboardを隠す
            self.dismissKeyboard()
            
            print(UserDefaults.standard.dictionaryRepresentation().filter { $0.key.hasPrefix("todoList") })
            
            
        } else {
            button.isEnabled = false
        }
        todoTableView.reloadData()
    }
    
    //buttonが押されたらキーボードを消す
    @objc func dismissKeyboard() {
        self.view.endEditing(true)
    }
    
}
//textViewに、テキストがあるか無いかを判別してる
extension ViewController: UITextViewDelegate {
    
    func textViewDidChangeSelection(_ textView: UITextView) {
        let addTextViewEmpty = addTextView.text?.isEmpty ?? true
        if addTextViewEmpty  {
            button.isEnabled = false
            button.setTitleColor(UIColor.systemGray , for: .normal)
        } else {
            button.isEnabled = true
            button.setTitleColor(UIColor.white , for: .normal)
            
        }
    }
}

//UISearcbarの処理を記述
extension ViewController: UISearchBarDelegate {
    
    //入力直後に検索が反映される
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        
        if searchField.text == "" {
            isSearching = false
            todoTableView.reloadData()
            print(isSearching)
        } else {
            searchResults = chats.filter({$0.lowercased().prefix(searchText.count) == searchText.lowercased()})
            isSearching = true
            todoTableView.reloadData()
            print(isSearching)
        }
    }
    //サーチバーで決定ボタンを押した時の動作(決定ボタンで検索したい時はこっちを使用 今回未使用)
    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        isSearching = false
        searchField.text = ""
        todoTableView.reloadData()
        print(isSearching)
    }
}

過去記事のTODOアプリのコードに対して、サーチバー追加後に変更した部位は以下。詳細は説明しませんが、サーチバーに文字が入力された直後に検索できるコードになってます。

//サーチバーをひも付け
    @IBOutlet weak var searchField: UISearchBar!
//SearchBar用に空の変数を準備 下の2つ
    var searchResults:[String] = []
    var isSearching = false
    //セルの個数を指定
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        
        if isSearching == true {
            return searchResults.count
        } else {
            return chats.count
        }
    }
    //セルはTableViewCellから情報取ってくる
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! TableViewCell
        if isSearching {
            cell.textView.text = searchResults[indexPath.row]
        } else {
            cell.textView.text = chats[indexPath.row]
        }
        return cell
    }
//サーチバーの処理を記述
extension ViewController: UISearchBarDelegate {
    
    //入力直後に検索が反映される
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        
        if searchField.text == "" {
            isSearching = false
            todoTableView.reloadData()
            print(isSearching)
        } else {
            searchResults = chats.filter({$0.lowercased().prefix(searchText.count) == searchText.lowercased()})
            isSearching = true
            todoTableView.reloadData()
            print(isSearching)
        }
    }
    //サーチバーで決定ボタンを押した時の動作(決定ボタンで検索したい時はこっちを使用 今回未使用)
    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        isSearching = false
        searchField.text = ""
        todoTableView.reloadData()
        print(isSearching)
    }
}

おしまい(´∀`)

コメント

タイトルとURLをコピーしました