Searchbar shows right result, leads to wrong Viewcontroller

Asked

Viewed 123 times

1

I’m putting together an app that shows managers on Page1 and their respective employees on Page2. I decided to mount a plist and press a Tableview, see:

plist and storyboard

To load the plist correctly insert to Appdelegate the following code:

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        if let url = Bundle.main.url(forResource: "directory", withExtension: "plist"), let array = NSArray(contentsOf: url) as? [[String:Any]] {
            Shared.instance.employees = array.map{Employee(dictionary: $0)}
        }
        return true
}

I also have this Structure helping me with all this:

struct EmployeeDetails {
    let functionary: String
    let imageFace: String
    let phone: String

    init(dictionary: [String: Any]) {
        self.functionary = (dictionary["Functionary"] as? String) ?? ""
        self.imageFace = (dictionary["ImageFace"] as? String) ?? ""
        self.phone = (dictionary["Phone"] as? String) ?? ""
    }
}
struct Employee {
    let position: String
    let name: String
    let details: [EmployeeDetails] // [String:Any]

    init(dictionary: [String: Any]) {
        self.position = (dictionary["Position"] as? String) ?? ""
        self.name = (dictionary["Name"] as? String) ?? ""

        let t = (dictionary["Details"] as? [Any]) ?? []
        self.details = t.map({EmployeeDetails(dictionary: $0 as! [String : Any])})
    }
}

struct Shared {
    static var instance = Shared()
    var employees: [Employee] = []
}

So far so good, but I inserted a Searchbar that shows me the correct results, but when I play "Suzan Brown," I see the employees of "John Smith,". I don’t know if the mistake is in segue... Could someone help me? Below, my Tableviewcontroller, I know there is something wrong, but I do not know exactly what...

class Page1: UITableViewController, UISearchBarDelegate {

    @IBOutlet weak var searchBar: UISearchBar!

    var employeesSearching = [Employee]()
    var isSearching : Bool = false

    override func viewDidLoad() {
        super.viewDidLoad()

        self.searchBar.delegate = self
    }

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if self.isSearching == true {
            return self.employeesSearching.count
        } else {
            return Shared.instance.employees.count
        }
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell1
        let employee = Shared.instance.employees[indexPath.row]

        if self.isSearching == true {
            cell.nameLabel.text = self.employeesSearching[indexPath.row].name
            cell.positionLabel.text = self.employeesSearching[indexPath.row].position
        } else {
            cell.nameLabel.text = employee.name
            cell.positionLabel.text = employee.position
        }

        return cell
    }

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        if self.searchBar.text!.isEmpty {
            self.isSearching = false
            self.tableView.reloadData()
        } else {
            self.isSearching = true
            self.employeesSearching.removeAll(keepingCapacity: false)
            let searchText = self.searchBar.text!.lowercased()
            for employee in Shared.instance.employees {

                if employee.name.lowercased().range(of: searchText) != nil {
                    self.employeesSearching.append(employee)
                }
            }
        }
            self.tableView.reloadData()
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let destination = segue.destination as? Page2,
            let indexPath = tableView.indexPathForSelectedRow {
            destination.newPage = Shared.instance.employees[indexPath.row]
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}
  • 1

    In your numberOfRowsInSection function switch to return isSearching ? employeesSearching.count : Shared.instance.employees.count

  • 1

    In its function cellForRowAt if self.isSearching == true { is redundant switch to if isSearching {

  • In this case use self.isSearching and isSearching makes no difference?

  • 1

    It does not differentiate any. There are exceptions but most of the time you do not need to specify self

2 answers

1

Put a trace from Cell to the other view. Then take a look at your prepareForSegue function. I recommend creating a custom class for your phone.

getting something like this:

class CustonTableViewCell: UITableViewCell {

    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var positionLabel: UILabel!

    var employee: Employee? {
        didSet {
            guard let employee = employee else { return }
            nameLabel.text = employee.name
            positionLabel.text = tipoBoleto.descricao
        }
    }

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

}

Back to the class that has your table, now you will put the data of your prepares for follows:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "ShowP2" {
        if let cell = sender as? CustonTableViewCell, let employee = cell.employee {
            if let vc = segue.destination as? Page2 {
                // Aqui você passa o objeto que esta em sua cell customizada para a outra tela
                vc.employee = employee
            }
        }
    }
}

Customizing a Cell will give you greater control over what is being presented.

  • The idea of customizing Cell is excellent! You can be sure that I will put it into practice. However, your …prepare(for segue… does not work concurrently with the searchBar when I touch a searched item. What I did below worked. But thanks anyway.

-1


I managed to solve!

Just make a few changes to the segue, I’ll put the before and the after for comparison purposes:

--- BEFORE ---

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let destination = segue.destination as? Page2,
        let indexPath = tableView.indexPathForSelectedRow {
        destination.newPage = Shared.instance.employees[indexPath.row]
    }
}

--- AFTERWARD ---

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "ShowP2" {
        if let indexPath = tableView.indexPathForSelectedRow {
            let employee: Employee
            if isSearching == true && searchBar.text != "" {
                employee = employeesSearching[indexPath.row]
            } else {
                employee = Shared.instance.employees[indexPath.row]
            }
            let destination = segue.destination as? Page2
            destination?.newPage = employee
        }
    }
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.