如何判断自定义 UISearchBar 中的 UITableView 是否被触摸?
How to tell if UITableView in custom UISearchBar is touched?
我正在尝试创建一个自定义 UISearchBar,它被放置为 navigationController
的 titleView
。使用下面的代码,建议的 suggestionTableView
完美出现;但是,它不识别任何水龙头。事实上,就好像 suggestionTableView
根本不存在一样,因为在建议 suggestionTableView
下,我的点击被发送到另一个视图。我被告知我可以使用 hitTest(...)
来捕捉这些触摸,但我不知道如何在我的 SuggestionSearchBar
或 ViewController
中实现它。我怎样才能将这些触摸发送到 suggestionTableView
?
SuggestionSearchBar
class SuggestionSearchBar: UISearchBar, UISearchBarDelegate {
var suggestionTableView = UITableView(frame: .zero)
let allPossibilities: [String]!
var possibilities = [String]()
//let del: UISearchBarDelegate!
init(del: UISearchBarDelegate, dropDownPossibilities: [String]) {
self.allPossibilities = dropDownPossibilities
super.init(frame: .zero)
isUserInteractionEnabled = true
delegate = del
searchTextField.addTarget(self, action: #selector(searchBar(_:)), for: .editingChanged)
searchTextField.addTarget(self, action: #selector(searchBarCancelButtonClicked(_:)), for: .editingDidEnd)
sizeToFit()
addTableView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func addTableView() {
let cellHeight = UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: "").frame.height
suggestionTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
suggestionTableView.backgroundColor = UIColor.clear
//suggestionTableView.separatorStyle = .none
suggestionTableView.tableFooterView = UIView()
addSubview(suggestionTableView)
suggestionTableView.delegate = self
suggestionTableView.dataSource = self
suggestionTableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
suggestionTableView.topAnchor.constraint(equalTo: bottomAnchor),
suggestionTableView.rightAnchor.constraint(equalTo: rightAnchor),
suggestionTableView.leftAnchor.constraint(equalTo: leftAnchor),
suggestionTableView.heightAnchor.constraint(equalToConstant: cellHeight*6),
])
hideSuggestions()
}
func showSuggestions() {
let sv = suggestionTableView.superview
sv?.clipsToBounds = false
suggestionTableView.isHidden = false
}
func hideSuggestions() {
suggestionTableView.isHidden = true
}
@objc func searchBar(_ searchBar: UISearchBar) {
print(searchBar.text?.uppercased() ?? "")
showSuggestions()
possibilities = allPossibilities.filter {[=10=].contains(searchBar.text?.uppercased() ?? "")}
print(possibilities.count)
suggestionTableView.reloadData()
if searchBar.text == "" || possibilities.count == 0 {
hideSuggestions()
}
}
@objc func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
hideSuggestions()
}
}
extension SuggestionSearchBar: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return possibilities.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = suggestionTableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.backgroundColor = UIColor(red: 0.25, green: 0.25, blue: 0.25, alpha: 0.75)
if traitCollection.userInterfaceStyle == .light {
cell.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.75)
}
cell.textLabel?.text = possibilities[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//add method that fills in and searches based on the text in that indexpath.row
print("selected")
}
}
ViewController
import UIKit
class ViewController: UIViewController {
lazy var searchBar = SuggestionSearchBar(del: self, dropDownPossibilities: ["red","green","blue","yellow"])
override func viewDidLoad() {
super.viewDidLoad()
setUpUI()
}
func setUpUI() {
setUpSearchBar()
}
}
extension ViewController: UISearchBarDelegate {
func setUpSearchBar() {
searchBar.searchBarStyle = UISearchBar.Style.prominent
searchBar.placeholder = "Search"
searchBar.sizeToFit()
searchBar.isTranslucent = false
searchBar.backgroundImage = UIImage()
searchBar.delegate = self
navigationItem.titleView = searchBar
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
print(searchBar.text!)
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.endEditing(true)
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
}
}
只要您将 UITableView
作为子视图添加到 SearchBar
或 UINavigationBar
,您就会不断发现这些触摸问题。
一种可能的处理方法是在调用站点有一个空容器 UIView
实例(在您的情况下为 ViewController
)并要求 SuggestionsSearchBar
添加它的 tableView
在那个容器里。
SuggestionSearchBar(
del: self,
suggestionsListContainer: <UIStackView_Inside_ViewController>,
dropDownPossibilities: ["red","green","blue","yellow"]
)
SuggestionsSearchBar
仍将管理有关 tableView 的数据源、委托、它的可见性等的所有内容。它只需要一个可以从调用站点保存它的 tableView 的视图。
更新
我只强调了需要更改的相关部分 - 其他一切都保持不变。
class SuggestionSearchBar: UISearchBar, UISearchBarDelegate {
init(del: UISearchBarDelegate, suggestionsListContainer: UIStackView, dropDownPossibilities: [String]) {
//// All the current setUp
addTableView(in: suggestionsListContainer)
}
private func addTableView(in container: UIStackView) {
//// All the current setUp
container.addArrangedSubview(suggestionTableView)
NSLayoutConstraint.activate([
suggestionTableView.heightAnchor.constraint(equalToConstant: cellHeight*6),
/// We need to assign only height here
/// top, leading, trailing will be driven by container at call site
])
}
}
class ViewController: UIViewController {
lazy var suggestionsListContainer: UIStackView = {
let stackView = UIStackView()
stackView.axis = .vertical
stackView.distribution = .fill
stackView.translatesAutoresizingMaskIntoConstraints = false
return stackView
}()
lazy var searchBar = SuggestionSearchBar(
del: self,
suggestionsListContainer: suggestionsListContainer,
dropDownPossibilities: ["red","green","blue","yellow"]
)
func setUpUI() {
setUpSearchBar()
setUpSuggestionsListContainer()
}
func setUpSuggestionsListContainer() {
self.view.addSubview(suggestionsListContainer)
NSLayoutConstraint.activate([
suggestionsListContainer.topAnchor.constraint(equalTo: self.view.topAnchor),
suggestionsListContainer.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
suggestionsListContainer.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
/// Height is not needed as it will be driven by tableView's height
])
}
}
查看您提供的代码,我可以使 UI 正常工作,甚至可以在 SuggestionSearchBar
中获得 UITableViewDelegate
回调。
这是变化
建议搜索栏
class SuggestionSearchBar: UISearchBar, UISearchBarDelegate {
var suggestionTableView = UITableView(frame: .zero)
let allPossibilities: [String]!
var possibilities = [String]()
var fromController: UIViewController?
//let del: UISearchBarDelegate!
init(del: UISearchBarDelegate, dropDownPossibilities: [String], fromController: UIViewController) {
self.fromController = fromController
self.allPossibilities = dropDownPossibilities
super.init(frame: .zero)
isUserInteractionEnabled = true
delegate = del
searchTextField.addTarget(self, action: #selector(searchBar(_:)), for: .editingChanged)
searchTextField.addTarget(self, action: #selector(searchBarCancelButtonClicked(_:)), for: .editingDidEnd)
sizeToFit()
addTableView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func addTableView() {
guard let view = fromController?.view else {return}
let cellHeight = UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: "").frame.height
suggestionTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
suggestionTableView.backgroundColor = UIColor.clear
//suggestionTableView.separatorStyle = .none
suggestionTableView.tableFooterView = UIView()
view.addSubview(suggestionTableView)
// addSubview(suggestionTableViewse
suggestionTableView.delegate = self
suggestionTableView.dataSource = self
suggestionTableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
suggestionTableView.topAnchor.constraint(equalTo: view.topAnchor),
suggestionTableView.rightAnchor.constraint(equalTo: view.rightAnchor),
suggestionTableView.leftAnchor.constraint(equalTo: view.leftAnchor),
suggestionTableView.heightAnchor.constraint(equalToConstant: cellHeight*6),
])
hideSuggestions()
}
func showSuggestions() {
let sv = suggestionTableView.superview
sv?.clipsToBounds = false
suggestionTableView.isHidden = false
}
func hideSuggestions() {
suggestionTableView.isHidden = true
}
@objc func searchBar(_ searchBar: UISearchBar) {
print(searchBar.text?.uppercased() ?? "")
showSuggestions()
possibilities = allPossibilities.filter {[=10=].contains(searchBar.text?.lowercased() ?? "")}
print(possibilities.count)
suggestionTableView.reloadData()
if searchBar.text == "" || possibilities.count == 0 {
hideSuggestions()
}
}
@objc func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
hideSuggestions()
}
}
ViewController
class ViewController: UIViewController {
lazy var searchBar = SuggestionSearchBar(del: self, dropDownPossibilities: ["red","green","blue","yellow"], fromController: self)
override func viewDidLoad() {
super.viewDidLoad()
setUpUI()
}
func setUpUI() {
setUpSearchBar()
}
}
为了总结变化,上面的代码尝试添加 suggestionTableView
到 SearchBarView 这是不可能的所以我用存储为
的父 ViewController 的引用初始化了 SearchBarView
var fromController: UIViewController?
这个属性后来用在addTableView()
private func addTableView() {
guard let view = fromController?.view else {return}
let cellHeight = UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: "").frame.height
suggestionTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
suggestionTableView.backgroundColor = UIColor.clear
//suggestionTableView.separatorStyle = .none
suggestionTableView.tableFooterView = UIView()
view.addSubview(suggestionTableView)
// addSubview(suggestionTableViewse
suggestionTableView.delegate = self
suggestionTableView.dataSource = self
suggestionTableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
suggestionTableView.topAnchor.constraint(equalTo: view.topAnchor),
suggestionTableView.rightAnchor.constraint(equalTo: view.rightAnchor),
suggestionTableView.leftAnchor.constraint(equalTo: view.leftAnchor),
suggestionTableView.heightAnchor.constraint(equalToConstant: cellHeight*6),
])
hideSuggestions()
}
还有一个小变化
possibilities = allPossibilities.filter {[=14=].contains(searchBar.text?.lowercased() ?? "")}
在@objc func searchBar(_ searchBar: UISearchBar) {
结果
我正在尝试创建一个自定义 UISearchBar,它被放置为 navigationController
的 titleView
。使用下面的代码,建议的 suggestionTableView
完美出现;但是,它不识别任何水龙头。事实上,就好像 suggestionTableView
根本不存在一样,因为在建议 suggestionTableView
下,我的点击被发送到另一个视图。我被告知我可以使用 hitTest(...)
来捕捉这些触摸,但我不知道如何在我的 SuggestionSearchBar
或 ViewController
中实现它。我怎样才能将这些触摸发送到 suggestionTableView
?
SuggestionSearchBar
class SuggestionSearchBar: UISearchBar, UISearchBarDelegate {
var suggestionTableView = UITableView(frame: .zero)
let allPossibilities: [String]!
var possibilities = [String]()
//let del: UISearchBarDelegate!
init(del: UISearchBarDelegate, dropDownPossibilities: [String]) {
self.allPossibilities = dropDownPossibilities
super.init(frame: .zero)
isUserInteractionEnabled = true
delegate = del
searchTextField.addTarget(self, action: #selector(searchBar(_:)), for: .editingChanged)
searchTextField.addTarget(self, action: #selector(searchBarCancelButtonClicked(_:)), for: .editingDidEnd)
sizeToFit()
addTableView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func addTableView() {
let cellHeight = UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: "").frame.height
suggestionTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
suggestionTableView.backgroundColor = UIColor.clear
//suggestionTableView.separatorStyle = .none
suggestionTableView.tableFooterView = UIView()
addSubview(suggestionTableView)
suggestionTableView.delegate = self
suggestionTableView.dataSource = self
suggestionTableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
suggestionTableView.topAnchor.constraint(equalTo: bottomAnchor),
suggestionTableView.rightAnchor.constraint(equalTo: rightAnchor),
suggestionTableView.leftAnchor.constraint(equalTo: leftAnchor),
suggestionTableView.heightAnchor.constraint(equalToConstant: cellHeight*6),
])
hideSuggestions()
}
func showSuggestions() {
let sv = suggestionTableView.superview
sv?.clipsToBounds = false
suggestionTableView.isHidden = false
}
func hideSuggestions() {
suggestionTableView.isHidden = true
}
@objc func searchBar(_ searchBar: UISearchBar) {
print(searchBar.text?.uppercased() ?? "")
showSuggestions()
possibilities = allPossibilities.filter {[=10=].contains(searchBar.text?.uppercased() ?? "")}
print(possibilities.count)
suggestionTableView.reloadData()
if searchBar.text == "" || possibilities.count == 0 {
hideSuggestions()
}
}
@objc func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
hideSuggestions()
}
}
extension SuggestionSearchBar: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return possibilities.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = suggestionTableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.backgroundColor = UIColor(red: 0.25, green: 0.25, blue: 0.25, alpha: 0.75)
if traitCollection.userInterfaceStyle == .light {
cell.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.75)
}
cell.textLabel?.text = possibilities[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//add method that fills in and searches based on the text in that indexpath.row
print("selected")
}
}
ViewController
import UIKit
class ViewController: UIViewController {
lazy var searchBar = SuggestionSearchBar(del: self, dropDownPossibilities: ["red","green","blue","yellow"])
override func viewDidLoad() {
super.viewDidLoad()
setUpUI()
}
func setUpUI() {
setUpSearchBar()
}
}
extension ViewController: UISearchBarDelegate {
func setUpSearchBar() {
searchBar.searchBarStyle = UISearchBar.Style.prominent
searchBar.placeholder = "Search"
searchBar.sizeToFit()
searchBar.isTranslucent = false
searchBar.backgroundImage = UIImage()
searchBar.delegate = self
navigationItem.titleView = searchBar
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
print(searchBar.text!)
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.endEditing(true)
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
}
}
只要您将 UITableView
作为子视图添加到 SearchBar
或 UINavigationBar
,您就会不断发现这些触摸问题。
一种可能的处理方法是在调用站点有一个空容器 UIView
实例(在您的情况下为 ViewController
)并要求 SuggestionsSearchBar
添加它的 tableView
在那个容器里。
SuggestionSearchBar(
del: self,
suggestionsListContainer: <UIStackView_Inside_ViewController>,
dropDownPossibilities: ["red","green","blue","yellow"]
)
SuggestionsSearchBar
仍将管理有关 tableView 的数据源、委托、它的可见性等的所有内容。它只需要一个可以从调用站点保存它的 tableView 的视图。
更新
我只强调了需要更改的相关部分 - 其他一切都保持不变。
class SuggestionSearchBar: UISearchBar, UISearchBarDelegate {
init(del: UISearchBarDelegate, suggestionsListContainer: UIStackView, dropDownPossibilities: [String]) {
//// All the current setUp
addTableView(in: suggestionsListContainer)
}
private func addTableView(in container: UIStackView) {
//// All the current setUp
container.addArrangedSubview(suggestionTableView)
NSLayoutConstraint.activate([
suggestionTableView.heightAnchor.constraint(equalToConstant: cellHeight*6),
/// We need to assign only height here
/// top, leading, trailing will be driven by container at call site
])
}
}
class ViewController: UIViewController {
lazy var suggestionsListContainer: UIStackView = {
let stackView = UIStackView()
stackView.axis = .vertical
stackView.distribution = .fill
stackView.translatesAutoresizingMaskIntoConstraints = false
return stackView
}()
lazy var searchBar = SuggestionSearchBar(
del: self,
suggestionsListContainer: suggestionsListContainer,
dropDownPossibilities: ["red","green","blue","yellow"]
)
func setUpUI() {
setUpSearchBar()
setUpSuggestionsListContainer()
}
func setUpSuggestionsListContainer() {
self.view.addSubview(suggestionsListContainer)
NSLayoutConstraint.activate([
suggestionsListContainer.topAnchor.constraint(equalTo: self.view.topAnchor),
suggestionsListContainer.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
suggestionsListContainer.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
/// Height is not needed as it will be driven by tableView's height
])
}
}
查看您提供的代码,我可以使 UI 正常工作,甚至可以在 SuggestionSearchBar
中获得 UITableViewDelegate
回调。
这是变化
建议搜索栏
class SuggestionSearchBar: UISearchBar, UISearchBarDelegate {
var suggestionTableView = UITableView(frame: .zero)
let allPossibilities: [String]!
var possibilities = [String]()
var fromController: UIViewController?
//let del: UISearchBarDelegate!
init(del: UISearchBarDelegate, dropDownPossibilities: [String], fromController: UIViewController) {
self.fromController = fromController
self.allPossibilities = dropDownPossibilities
super.init(frame: .zero)
isUserInteractionEnabled = true
delegate = del
searchTextField.addTarget(self, action: #selector(searchBar(_:)), for: .editingChanged)
searchTextField.addTarget(self, action: #selector(searchBarCancelButtonClicked(_:)), for: .editingDidEnd)
sizeToFit()
addTableView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func addTableView() {
guard let view = fromController?.view else {return}
let cellHeight = UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: "").frame.height
suggestionTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
suggestionTableView.backgroundColor = UIColor.clear
//suggestionTableView.separatorStyle = .none
suggestionTableView.tableFooterView = UIView()
view.addSubview(suggestionTableView)
// addSubview(suggestionTableViewse
suggestionTableView.delegate = self
suggestionTableView.dataSource = self
suggestionTableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
suggestionTableView.topAnchor.constraint(equalTo: view.topAnchor),
suggestionTableView.rightAnchor.constraint(equalTo: view.rightAnchor),
suggestionTableView.leftAnchor.constraint(equalTo: view.leftAnchor),
suggestionTableView.heightAnchor.constraint(equalToConstant: cellHeight*6),
])
hideSuggestions()
}
func showSuggestions() {
let sv = suggestionTableView.superview
sv?.clipsToBounds = false
suggestionTableView.isHidden = false
}
func hideSuggestions() {
suggestionTableView.isHidden = true
}
@objc func searchBar(_ searchBar: UISearchBar) {
print(searchBar.text?.uppercased() ?? "")
showSuggestions()
possibilities = allPossibilities.filter {[=10=].contains(searchBar.text?.lowercased() ?? "")}
print(possibilities.count)
suggestionTableView.reloadData()
if searchBar.text == "" || possibilities.count == 0 {
hideSuggestions()
}
}
@objc func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
hideSuggestions()
}
}
ViewController
class ViewController: UIViewController {
lazy var searchBar = SuggestionSearchBar(del: self, dropDownPossibilities: ["red","green","blue","yellow"], fromController: self)
override func viewDidLoad() {
super.viewDidLoad()
setUpUI()
}
func setUpUI() {
setUpSearchBar()
}
}
为了总结变化,上面的代码尝试添加 suggestionTableView
到 SearchBarView 这是不可能的所以我用存储为
var fromController: UIViewController?
这个属性后来用在addTableView()
private func addTableView() {
guard let view = fromController?.view else {return}
let cellHeight = UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: "").frame.height
suggestionTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
suggestionTableView.backgroundColor = UIColor.clear
//suggestionTableView.separatorStyle = .none
suggestionTableView.tableFooterView = UIView()
view.addSubview(suggestionTableView)
// addSubview(suggestionTableViewse
suggestionTableView.delegate = self
suggestionTableView.dataSource = self
suggestionTableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
suggestionTableView.topAnchor.constraint(equalTo: view.topAnchor),
suggestionTableView.rightAnchor.constraint(equalTo: view.rightAnchor),
suggestionTableView.leftAnchor.constraint(equalTo: view.leftAnchor),
suggestionTableView.heightAnchor.constraint(equalToConstant: cellHeight*6),
])
hideSuggestions()
}
还有一个小变化
possibilities = allPossibilities.filter {[=14=].contains(searchBar.text?.lowercased() ?? "")}
在@objc func searchBar(_ searchBar: UISearchBar) {
结果