iOS17适配指南之UIContentUnavailableView(一)主要讲解了 UIContentUnavailableView 的基本使用与 UIContentUnavailableConfiguration 的两种配置empty()
、loading()
。本文将介绍另外一种配置search()
以及如何使用 SwiftUI 自定义配置。
import UIKit
class ViewController: UIViewController {
lazy var tableView: UITableView = {
let tableView = UITableView(frame: UIScreen.main.bounds)
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "abc")
tableView.dataSource = self
tableView.rowHeight = 60.0
return tableView
}()
lazy var schoolSearchController: UISearchController = {
let controller = UISearchController(searchResultsController: nil)
controller.searchBar.searchBarStyle = .minimal
controller.searchBar.sizeToFit()
controller.searchResultsUpdater = self
controller.searchBar.delegate = self
return controller
}()
let schoolArray = ["清华大学", "北京大学", "中国人民大学", "北京交通大学", "北京工业大学",
"北京航空航天大学", "北京理工大学", "北京科技大学", "中国政法大学",
"中央财经大学", "华北电力大学", "北京体育大学", "上海外国语大学", "复旦大学",
"华东师范大学", "上海交通大学", "同济大学", "上海财经大学", "华东理工大学"]
var searchArray: [String] = [] {
didSet {
tableView.reloadData()
// 让系统调用updateContentUnavailableConfiguration(using: state)方法
setNeedsUpdateContentUnavailableConfiguration()
}
}
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(tableView)
tableView.tableHeaderView = schoolSearchController.searchBar
}
override func updateContentUnavailableConfiguration(using state: UIContentUnavailableConfigurationState) {
// 更新UISearchController的contentUnavailableConfiguration
let config: UIContentUnavailableConfiguration? = searchArray.isEmpty ? .search() : nil
schoolSearchController.contentUnavailableConfiguration = config
}
}
// MARK: - UITableViewDataSource
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if schoolSearchController.isActive {
return searchArray.count
} else {
return schoolArray.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
-> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "abc", for: indexPath)
if schoolSearchController.isActive {
cell.textLabel?.text = searchArray[indexPath.row]
return cell
} else {
cell.textLabel?.text = schoolArray[indexPath.row]
return cell
}
}
}
// MARK: - UISearchResultsUpdating
extension ViewController: UISearchResultsUpdating {
// MARK: 实时搜索
func updateSearchResults(for searchController: UISearchController) {
if let text = searchController.searchBar.text {
searchArray = schoolArray.filter { school -> Bool in
school.contains(text)
}
}
}
}
// MARK: - UISearchBarDelegate
extension ViewController: UISearchBarDelegate {
// MARK: 点击搜索
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
if let text = searchBar.text {
searchArray = schoolArray.filter { school -> Bool in
school.contains(text)
}
}
}
// MARK: 点击取消
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchArray = schoolArray
}
}
案例三.gif
import SwiftUI
import UIKit
class ViewController: UIViewController {
lazy var emptyConfig: UIContentUnavailableConfiguration = {
var config = UIContentUnavailableConfiguration.empty()
config.text = "暂无数据"
config.image = UIImage(systemName: "exclamationmark.triangle")
return config
}()
override func viewDidLoad() {
super.viewDidLoad()
contentUnavailableConfiguration = emptyConfig
}
override func updateContentUnavailableConfiguration(using state: UIContentUnavailableConfigurationState) {
// 使用SwiftUI自定义配置
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
let loadingConfig = UIHostingConfiguration {
VStack(spacing: 20) {
ProgressView()
Text("正在加载数据...")
.foregroundStyle(.secondary)
}
}
self.contentUnavailableConfiguration = loadingConfig
}
// 移除
DispatchQueue.main.asyncAfter(deadline: .now() + 6) {
self.contentUnavailableConfiguration = nil
self.view.backgroundColor = .systemTeal
}
}
}
案例四.gif