单击“搜索”按钮时的奇怪行为
Posted
技术标签:
【中文标题】单击“搜索”按钮时的奇怪行为【英文标题】:Odd behavior when clicking "Search" button 【发布时间】:2018-01-14 16:00:21 【问题描述】:我真的很喜欢 ios 11.0 附带的 UISearchBar 的新设计。我正在尝试在我自己的应用程序中包含一个搜索栏。 该应用程序由一个导航控制器组成。我正在尝试在我的 UITableViewController 实例之一中包含搜索栏。
这里是棘手的部分。只要搜索字段处于活动状态(即是第一响应者),我就无法导航表格视图。当我单击键盘上的“搜索”按钮时,键盘按预期消失,但 UITableView 仍然没有响应。一旦我点击 UItableView,常规行为就会“恢复”。但随后 UISearchBar 文本被重置为空字符串(不是我)。我错过了什么吗?我很确定一切都已正确连接。
这里是完整的代码:
class StravaSelectionViewController : UITableViewController,
UISearchBarDelegate, MKMapViewDelegate
private let searchController = UISearchController(searchResultsController: nil)
private var allActivities: [ActivitySummary] = []
private var allRoutes: [RouteSummary] = []
private var allSegments: [SegmentSummary] = []
private var activities: [ActivitySummary] = []
private var routes: [RouteSummary] = []
private var segments: [SegmentSummary] = []
var mode: StravaLoadMode = .none
var activitySelected: ((ActivitySummary) -> ())?
var segmentSelected: ((SegmentSummary) -> ())?
var routeSelected: ((RouteSummary) -> ())?
override func viewDidLoad()
super.viewDidLoad()
self.tableView.tableFooterView = UIView()
self.initSearchBar()
override func viewDidAppear(_ animated: Bool)
super.viewDidAppear(animated)
self.refresh()
override func viewDidDisappear(_ animated: Bool)
super.viewDidAppear(animated)
self.allActivities.removeAll()
self.allRoutes.removeAll()
self.allSegments.removeAll()
self.activities.removeAll()
self.routes.removeAll()
self.segments.removeAll()
fileprivate func initSearchBar()
self.definesPresentationContext = true
self.searchController.searchBar.delegate = self
self.searchController.searchBar.placeholder = Resources.SEARCH_PLACEHOLDER
self.searchController.searchBar.showsScopeBar = false
self.navigationItem.searchController = searchController
self.navigationItem.searchController?.searchBar.tintColor = UIColor.white
// MARK: Refresh
fileprivate func refresh()
switch self.mode
case .activities:
self.loadActivities()
break
case .routes:
self.loadRoutes()
break
case .segments:
self.loadSegments()
break
default:
break
fileprivate func loadActivities()
Indicator.shared.present(self, Resources.LOADING_ACTIVITIES, true)
let client: ActivityClient = ActivityClient()
client.getActivities(1, 200)
activities in
self.allActivities.append(contentsOf: activities)
self.activities.append(contentsOf: activities)
DispatchQueue.main.async
self.tableView.reloadData()
Indicator.shared.dismiss(true)
fileprivate func loadRoutes()
guard let athleteId = Settings.getAthleteId() else return
Indicator.shared.present(self, Resources.LOADING_ROUTES, true)
let client = RouteClient()
client.getRoutes(athleteId)
routes in
self.routes.append(contentsOf: routes)
self.allRoutes.append(contentsOf: routes)
DispatchQueue.main.async
self.tableView.reloadData()
Indicator.shared.dismiss(true)
fileprivate func loadSegments()
Indicator.shared.present(self, Resources.LOADING_SEGMENTS, true)
let client = SegmentClient()
client.getAllStarredSegments(page: 1)
segments, finished in
if let segments = segments
self.segments.append(contentsOf: segments)
self.allSegments.append(contentsOf: segments)
if finished == true
// Sort the segments alphabetically
self.segments.sort $0.name < $1.name
self.allSegments.sort $0.name < $1.name
DispatchQueue.main.async
self.tableView.reloadData()
Indicator.shared.dismiss(true)
// MARK: Table View
override func numberOfSections(in tableView: UITableView) -> Int
return 1
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
switch mode
case .activities:
return self.activities.count
case .routes:
return self.routes.count
case .segments:
return self.segments.count
default:
return 0
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
switch mode
case .activities:
return self.fillActivityCell(row: indexPath.row)
case .routes:
return self.fillRouteCell(row: indexPath.row)
case .segments:
return self.fillSegmentCell(row: indexPath.row)
default:
return UITableViewCell()
fileprivate func fillActivityCell(row: Int) -> ActivityCell
let cell = tableView.dequeueReusableCell(withIdentifier: "activityCell") as! ActivityCell
let activity = self.activities[row]
cell.activity = activity
cell.route = nil
cell.segment = nil
cell.name.text = activity.name
if let distance = activity.distance
cell.distance.text = Utilities.getUnitDistance(distance.floatValue)
if let elevation = activity.elevationGain
cell.elevation.text = Utilities.getUnitElevation(elevation.intValue)
// Map
if let map = activity.map
if let summary = map.summary
var coordinates = PolylineDecoder.decode(summary)
DispatchQueue.main.async
cell.map.layer.cornerRadius = 10.0
// Clear old overlays
cell.map.removeOverlays(cell.map.overlays)
cell.map.delegate = self
let polyline = MKPolyline(coordinates: &coordinates, count: coordinates.count)
cell.map.add(polyline)
cell.map.setRegion(MKCoordinateRegionForMapRect(polyline.boundingMapRect), animated: false)
return cell
fileprivate func fillRouteCell(row: Int) -> ActivityCell
let cell = tableView.dequeueReusableCell(withIdentifier: "activityCell") as! ActivityCell
let route = self.routes[row]
cell.route = route
cell.activity = nil
cell.segment = nil
cell.name.text = route.name
if let distance = route.distance
cell.distance.text = Utilities.getUnitDistance(distance.floatValue)
if let elevation = route.elevationGain
cell.elevation.text = Utilities.getUnitElevation(elevation.intValue)
// Map
if let map = route.map
if let summary = map.summary
var coordinates = PolylineDecoder.decode(summary)
DispatchQueue.main.async
cell.map.layer.cornerRadius = 8.0
// Clear old overlays
cell.map.removeOverlays(cell.map.overlays)
cell.map.delegate = self
let polyline = MKPolyline(coordinates: &coordinates, count: coordinates.count)
cell.map.add(polyline)
cell.map.setRegion(MKCoordinateRegionForMapRect(polyline.boundingMapRect), animated: false)
return cell
fileprivate func fillSegmentCell(row: Int) -> SegmentCell
let cell = tableView.dequeueReusableCell(withIdentifier: "segmentCell") as! SegmentCell
let segment = self.segments[row]
cell.name.text = segment.name
if let distance = segment.distance
cell.distance.text = Utilities.getUnitDistance(distance.floatValue)
if let city = segment.city, let state = segment.state, let country = segment.country
cell.location.text = String(format: "%@, %@, %@", city, state, country)
if let grade = segment.averageGrade
cell.averageGrade.text = String(format: "%.2f %%", grade.floatValue)
return cell
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
tableView.deselectRow(at: indexPath, animated: true)
switch mode
case .activities:
self.activitySelected?(self.activities[indexPath.row])
break
case .segments:
self.segmentSelected?(self.segments[indexPath.row])
break
case .routes:
self.routeSelected?(self.routes[indexPath.row])
break
case .none:
break
DispatchQueue.main.async
self.navigationController?.popToRootViewController(animated: true)
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
if mode == .segments
return 80.0
return 256.0
// MARK: Map
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer
let polylineRenderer = MKPolylineRenderer(overlay: overlay)
polylineRenderer.strokeColor = UIColor.red
polylineRenderer.lineWidth = 1
return polylineRenderer
// MARK: Selection Color
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
let selectionView = UIView()
selectionView.backgroundColor = UIColor(r: 40.0, g: 40.0, b: 40.0, alpha: 1.0)
cell.selectedBackgroundView = selectionView
// MARK: Search
private var searchBarIsEmpty: Bool
get return searchController.searchBar.text?.isEmpty ?? true
func searchBarCancelButtonClicked(_ searchBar: UISearchBar)
self.resetSearch()
func searchBarSearchButtonClicked(_ searchBar: UISearchBar)
Swift.print("Search clicked")
self.searchController.searchBar.endEditing(true)
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String)
self.filter(searchText)
self.tableView.reloadData()
fileprivate func filter(_ searchText: String)
if searchText.isEmpty
self.resetSearch()
else
let search = searchText.lowercased()
switch self.mode
case .activities:
self.filterActivities(search)
break
case .routes:
self.filterRoutes(search)
break
case .segments:
self.filterSegments(search)
break
default:
break
fileprivate func filterSegments(_ search: String)
self.segments = self.allSegments.filter( $0.name.lowercased().contains(search) )
fileprivate func filterRoutes(_ search: String)
self.routes = self.allRoutes.filter( $0.name.lowercased().contains(search) )
fileprivate func filterActivities(_ search: String)
self.activities = self.allActivities.filter( $0.name.lowercased().contains(search) )
fileprivate func resetSearch()
switch self.mode
case .activities:
self.activities.removeAll()
self.activities.append(contentsOf: self.allActivities)
break
case .routes:
self.routes.removeAll()
self.routes.append(contentsOf: self.allRoutes)
break
case .segments:
self.segments.removeAll()
self.segments.append(contentsOf: self.allSegments)
break
default:
break
self.tableView.reloadData()
【问题讨论】:
【参考方案1】:我找到了解决方案,供以后参考:
initSearchBar() 中缺少以下行:
self.searchController.obscuresBackgroundDuringPresentation = false
我希望这会有所帮助。
【讨论】:
以上是关于单击“搜索”按钮时的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章
将 UIButton 添加到 UICollectionViewCell 时的奇怪行为
将 Scaffold 放入 NestedScrollview 时的奇怪行为?在 SliverAppbar 下剪辑时自动滚动到顶部