edo oktarifa
edo oktarifa

Reputation: 63

how to search data from model in swift?

I want to search for some data in the table view using the search bar, but when I try to find data in my model, I'm not able to search that data.
I made a expand table view cell and created a search bar for searching data, but still I can't search the data in the model. How can I achieve that?

here is my code:

import UIKit

class FAQViewController: UIViewController, UITableViewDataSource {

    var dataFaq = [modelFAQ]()

    let items = [
        modelFAQ(name: "1. search box", description: "The design led users to instinctively search for their question first before clicking the FAQs"),
        modelFAQ(name: "2.list of FAQs ", description: "Customers clicked around on the FAQs first."),
        modelFAQ(name: "3. customers", description: "top issues first and then use the search for the questions instead of browsing and yielding more relevant results")

        ]

    @IBOutlet fileprivate weak var tableView: UITableView!
    @IBOutlet weak var searchDataBar: UISearchBar!
    fileprivate var indexPaths: Set<IndexPath> = []
    var cellIdentifier = "dataSourceFAQ"

    var searchData = [String]()
    var searching = false

    override var preferredStatusBarStyle: UIStatusBarStyle{
        return .lightContent
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        setupTableView()
        searchDataBar.delegate = self
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        if searching {
            return searchData.count
        }else {
            return items.count
        }
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! FAQTableViewCell

        if searching{
            cell.titleLabel.text = searchData[indexPath.row]
        }else{
            cell.titleLabel.text = items[indexPath.row].name
        }

        let nameDetail = self[indexPath].name as? String
        let description = self[indexPath].description


        cell.update(name: nameDetail ?? "0", description: description)


        cell.state = cellIsExpanded(at: indexPath) ? .expanded : .collapsed
        return cell
    }

    override func viewWillAppear(_ animated: Bool) {
        tabBarController?.tabBar.isHidden = true
    }

    private func setupTableView(){
        tableView.delegate = self
        tableView.dataSource = self
        tableView.rowHeight = UITableView.automaticDimension
        tableView.estimatedRowHeight = 200.0
        tableView.separatorStyle = .none
         }

     }

    extension FAQViewController: UITableViewDelegate{
        func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
            let cell = tableView.cellForRow(at: indexPath) as!FAQTableViewCell


            cell.state = .expanded
            self.addExpandedIndexPath(indexPath)

            tableView.beginUpdates()
            tableView.endUpdates()
            print("1")
        }

    func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
        let cell = tableView.cellForRow(at: indexPath) as! FAQTableViewCell

        cell.state = .collapsed
        self.removeExpandedIndexPath(indexPath)


        tableView.beginUpdates()
        tableView.endUpdates()
        print("2")
}
}

extension FAQViewController {
    func cellIsExpanded(at indexPath: IndexPath) -> Bool {
        return indexPaths.contains(indexPath)
    }

    func addExpandedIndexPath(_ indexPath: IndexPath) {
        indexPaths.insert(indexPath)
    }

    func removeExpandedIndexPath(_ indexPath: IndexPath) {
        indexPaths.remove(indexPath)
    }
}

extension FAQViewController {
    subscript(indexPath: IndexPath) -> modelFAQ {
        return items[indexPath.row]
    }
}


    extension FAQViewController: UISearchBarDelegate {

        func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {

            searchData = searchText.isEmpty ? items: items.filter{ $0.name(searchText)}

            searching = true
            tableView.reloadData()
        }
       }

here is my table view cell

    import UIKit

    class FAQTableViewCell: UITableViewCell {

        enum cellState{
            case collapsed
            case expanded

            var carretImage: UIImage {
                switch self {
                case .collapsed:
                    return UIImage(named: "ic_arrow_down")!
                case .expanded:
                    return UIImage(named: "ic_arrow_up")!
                }
            }

        }

        @IBOutlet private weak var stackView: UIStackView!
        @IBOutlet private weak var containerView: UIView!
        @IBOutlet weak var titleLabel: UILabel!
        @IBOutlet private weak var carret: UIImageView!
        @IBOutlet private weak var descriptionLabel: UILabel!


        private let expandedViewIndex: Int = 1

        var state: cellState = .expanded {
            didSet{
                toggle()
            }
        }

        override func awakeFromNib() {
            selectionStyle = .none
            containerView.layer.cornerRadius = 5.0
        }

        private func toggle(){
            stackView.arrangedSubviews[expandedViewIndex].isHidden = stateIsCollapsed()
            carret.image = state.carretImage
        }

        private func stateIsCollapsed() -> Bool{
            return state == .collapsed
        }

        func update(name: String, description: String){
            titleLabel.text = name
            descriptionLabel.text = description

        }
    }

here is my model

    struct modelFAQ {
        var name: String
        var description: String
    }

Upvotes: 0

Views: 3609

Answers (2)

vadian
vadian

Reputation: 285039

Two issues:

  1. You have to declare searchData as the same type as the main data.

    By the way according to the naming convention struct and class names start with a capital letter

    var searchData = [ModelFAQ]()
    
  2. The search filter closure is wrong. Write

    searchData = searchText.isEmpty ? items : items.filter{ $0.name.contains(searchText)}
    

    or if you want to search case insensitive

    searchData = searchText.isEmpty ? items : items.filter{ $0.name.range(of: searchText, options: .caseInsensitive) != nil }
    

And you have to change in cellForRowAt

cell.titleLabel.text = searchData[indexPath.row].name

Upvotes: 5

Muhammad Waqas Bhati
Muhammad Waqas Bhati

Reputation: 2805

NOTE: Always start class/struct name with CAPITAL LETTER

  • Wrong: modelFAQ

  • correct: ModelFAQ

You have made one mistake, you have to declare your searchData Array like below

var searchData = [ModelFAQ]()

and while in datasource method you have to get name from the ModelFAQ object and assign it to your label.

Hope it will help you.

Upvotes: 0

Related Questions