Search code examples
iosswifttableviewsearchbarfirst-responder

Change table when search bar becomes first responder - swift


Hi I'm trying to change the cells in my table when the search bar becomes first responder. Ideally I want my add friends table to display friend requests initially and when the search bar becomes first responder it will change the cells to display search results for things typed into the search bar. Here is my current code:

class UserFriendRequestController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {

let titleCell = "titleCell"
let cellId = "cellId"
let contactSearch = "contactSearch"
var searchBar = UISearchBar()
var addFriendsTable: UITableView = UITableView()
let users = NSMutableArray()

override func viewDidLoad() {
    super.viewDidLoad()

    view.addSubview(addFriendsTable)

    let img = UIImage(named: "white-screen")
    self.navigationController?.navigationBar.shadowImage = img
    self.navigationController?.navigationBar.setBackgroundImage(img, for: UIBarMetrics.default)

    navigationItem.title = "Add Contact"
    self.navigationController?.navigationBar.titleTextAttributes = [ NSFontAttributeName: UIFont(name: "Nunito", size: 18.5)!, NSForegroundColorAttributeName: UIColor(r: 86, g: 214, b: 209)]

    addFriendsTable.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height - (70))
    addFriendsTable.delegate = self
    addFriendsTable.dataSource = self
    searchBar.sizeToFit()
    searchBar.searchBarStyle = .minimal
    searchBar.placeholder = "Search Conctacts"
    searchBar.showsCancelButton = true
    searchBar.delegate = self
    addFriendsTable.tableHeaderView = searchBar
    addFriendsTable.contentOffset = CGPoint(x: 0.0, y: 0.0)

    UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).setTitleTextAttributes([NSFontAttributeName : UIFont(name: "Nunito", size: 15)!,  NSForegroundColorAttributeName : UIColor(r: 78, g: 78, b: 78)
        ], for: .normal)

    var image = UIImage(named: "back_button_thick")
    image = image?.withRenderingMode(UIImageRenderingMode.alwaysOriginal)
    navigationItem.leftBarButtonItem = UIBarButtonItem(image: image, style: .plain, target: self, action: #selector(handleBack))

    addFriendsTable.register(UserFriendRequestsCell.self, forCellReuseIdentifier: cellId)
    addFriendsTable.register(FriendRequestsTitleCell.self, forCellReuseIdentifier: titleCell)
    addFriendsTable.register(AddFriendRequestCell.self, forCellReuseIdentifier: contactSearch)
    addFriendsTable.separatorColor = UIColor(r: 225, g: 225, b: 225)

    setup()
}

func setup() {
    for i in 1 ..< 20 {
        let user = User()
        users.add(user)
    }
}


func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
    searchBar.text = nil
    searchBar.resignFirstResponder()
}

func handleBack() {
    dismiss(animated: true, completion: nil)
}


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

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    if self.searchBar.isFirstResponder {
        let cell = tableView.dequeueReusableCell(withIdentifier: contactSearch, for: indexPath) as! AddFriendRequestCell
        cell.selectionStyle = UITableViewCellSelectionStyle.none
        cell.textLabel?.text = "Instagram User Name"
        cell.textLabel?.font = UIFont(name: "Nunito", size: 16)
        cell.textLabel?.textColor = UIColor(r: 51, g: 51, b: 51)
        cell.detailTextLabel?.text = "Instagram Handle"
        cell.detailTextLabel?.font = UIFont(name: "Nunito", size: 13)
        cell.detailTextLabel?.textColor = UIColor.darkGray
        cell.profileImageView.image = UIImage(named: "profilepic")
        cell.separatorInset.left = CGFloat(55)
        cell.separatorInset.right = CGFloat(5)
        let user = users[indexPath.row] as! User
        cell.configure(user: user)
        return cell
    } else {
        if indexPath.row == 0 {

            let cell = tableView.dequeueReusableCell(withIdentifier: titleCell, for: indexPath) as! FriendRequestsTitleCell
            cell.selectionStyle = UITableViewCellSelectionStyle.none
            return cell

        } else {
            let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! UserFriendRequestsCell
            cell.selectionStyle = UITableViewCellSelectionStyle.none
            cell.textLabel?.text = "Instagram User Name"
            cell.textLabel?.font = UIFont(name: "Nunito", size: 16)
            cell.textLabel?.textColor = UIColor(r: 51, g: 51, b: 51)
            cell.detailTextLabel?.text = "Instagram Handle"
            cell.detailTextLabel?.font = UIFont(name: "Nunito", size: 13)
            cell.detailTextLabel?.textColor = UIColor.darkGray
            cell.profileImageView.image = UIImage(named: "profilepic")
            cell.separatorInset.left = CGFloat(55)
            cell.separatorInset.right = CGFloat(5)

            return cell
        }
    }
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat{

    if self.searchBar.isFirstResponder {
        return 55
    }

    else {
        if indexPath.row == 0 {
            return 30
        } else {
            return 55
        }
    }
}
}

Solution

  • For this, I would recommend looking at the other methods in UISearchBarDelegate, specifically searchBarTextDidBeginEditing() and searchBarTextDidEndEditing(). In each of these delegate methods you can call [self.tableView reloadData] to update all the cells.

    Also, another way to implement the FriendRequestsTitleCell would be to add a custom header view to your table view, since the cell you're using only ever appears at the top of the table view.