自定义单元格和默认单元格同时显示在 tableview 上
Both custom cell and default cell is showing together on tableview
我正在用 customCell
制作一个简单的 tableview
。和上面的 searchBar
。但从 tableView
得到了一个奇怪的行为。 customCell
正在显示,但在其上方 defaultCell
也显示并且数据正在填充到 defaultCell
中,尽管我正在 customCell
.
上设置数据
这是我得到的输出
https://i.imgur.com/xsTIsiz.png
如果仔细观察,您会看到我的自定义单元格 UI 显示在默认单元格下方。
我的自定义单元格:
https://i.imgur.com/J4UpRle.png
这是我来自 viewcontroller
的代码
import UIKit
class SuraSearchController: UIViewController {
let searchController = UISearchController(searchResultsController: nil)
let reciters = [Reciter(name: "Abdul Basit Abdus Samad", downloadUrl: ""),
Reciter(name: "Abdul Rahman Al-Sudais", downloadUrl: ""),
Reciter(name: "Ali Bin Abdur Rahman Al Huthaify", downloadUrl: ""),
Reciter(name: "Mishary Rashid Alafasy", downloadUrl: ""),
Reciter(name: "Cheik Mohamed Jibril", downloadUrl: ""),
Reciter(name: "Mohamed Siddiq El-Minshawi", downloadUrl: ""),
Reciter(name: "Mahmoud Khalil Al-Hussary", downloadUrl: ""),
Reciter(name: "Ibrahim Walk (English Only)", downloadUrl: ""),
Reciter(name: "Abu Bakr Al Shatri", downloadUrl: "")]
var filteredReciters = [Reciter]()
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// definesPresentationContext = true
initNavBar()
initTableView()
// Do any additional setup after loading the view.
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.navigationController?.setNavigationBarHidden(true, animated: animated)
}
func initNavBar() {
// show navbar
self.navigationController?.setNavigationBarHidden(false, animated: true)
// set search bar delegates
searchController.searchResultsUpdater = self
searchController.obscuresBackgroundDuringPresentation = false
// Customize Search Bar
searchController.searchBar.placeholder = "Search Friends"
let myString = "Cancel"
let myAttribute = [ NSAttributedStringKey.foregroundColor: UIColor.white ]
UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).title = myString
UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).setTitleTextAttributes(myAttribute, for: .normal)
if #available(iOS 11.0, *) {
let scb = searchController.searchBar
scb.tintColor = UIColor.white
scb.barTintColor = UIColor.white
if let textfield = scb.value(forKey: "searchField") as? UITextField {
textfield.textColor = UIColor.blue
if let backgroundview = textfield.subviews.first {
// Background color
backgroundview.backgroundColor = UIColor.white
// Rounded corner
backgroundview.layer.cornerRadius = 10
backgroundview.clipsToBounds = true
}
}
}
// Set search bar on navbar
navigationItem.searchController = searchController
navigationItem.hidesSearchBarWhenScrolling = false
}
func initTableView() {
tableView.dataSource = self
tableView.delegate = self
tableView.register(UINib(nibName: "SuraSearchCell", bundle: nil), forCellReuseIdentifier: "SuraSearchCell")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func searchBarIsEmpty() -> Bool {
// Returns true if the text is empty or nil
return searchController.searchBar.text?.isEmpty ?? true
}
func filterContentForSearchText(_ searchText: String, scope: String = "All") {
filteredReciters = reciters.filter({( reciter : Reciter) -> Bool in
return reciter.name.lowercased().contains(searchText.lowercased())
})
tableView.reloadData()
}
func isFiltering() -> Bool {
return searchController.isActive && !searchBarIsEmpty()
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
extension SuraSearchController: UITableViewDataSource, UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if isFiltering() {
return filteredReciters.count
}
return reciters.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "SuraSearchCell", for: indexPath) as? SuraSearchCell {
let candy: Reciter
if isFiltering() {
candy = filteredReciters[indexPath.row]
} else {
candy = reciters[indexPath.row]
}
cell.textLabel!.text = candy.name
return cell
}
return UITableViewCell()
}
}
extension SuraSearchController: UISearchResultsUpdating {
// MARK: - UISearchResultsUpdating Delegate
func updateSearchResults(for searchController: UISearchController) {
filterContentForSearchText(searchController.searchBar.text!)
}
}
以及表格视图单元格的代码
import UIKit
class SuraSearchCell: UITableViewCell {
@IBOutlet weak var itemTitle: UILabel!
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
}
func configureCell(item: Reciter) {
itemTitle.text = item.name
}
}
cell.textLabel
默认为 UITableViewCell
属性。您只需要为 customCell
itemTitle
标签设置值。
将 cell.textLabel!.text = candy.name
替换为 cell. itemTitle!.text = candy.name
,如下所示。
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "SuraSearchCell", for: indexPath) as? SuraSearchCell {
let candy: Reciter
if isFiltering() {
candy = filteredReciters[indexPath.row]
} else {
candy = reciters[indexPath.row]
}
cell. itemTitle!.text = candy.name
//OR
cell.configureCell(candy) // IF your candy is of Reciter type
return cell
}
return UITableViewCell()
}
重用标识符名称可能有误。将名称与代码中使用的名称匹配。
让 cellForRowAtIndex
更新如下
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "SuraSearchCell", for: indexPath) as? SuraSearchCell {
let candy: Reciter
if isFiltering() {
candy = filteredReciters[indexPath.row]
} else {
candy = reciters[indexPath.row]
}
cell.configureCell(candy)
return cell
}
return UITableViewCell()
}
我正在用 customCell
制作一个简单的 tableview
。和上面的 searchBar
。但从 tableView
得到了一个奇怪的行为。 customCell
正在显示,但在其上方 defaultCell
也显示并且数据正在填充到 defaultCell
中,尽管我正在 customCell
.
这是我得到的输出
https://i.imgur.com/xsTIsiz.png
如果仔细观察,您会看到我的自定义单元格 UI 显示在默认单元格下方。
我的自定义单元格:
https://i.imgur.com/J4UpRle.png
这是我来自 viewcontroller
的代码import UIKit
class SuraSearchController: UIViewController {
let searchController = UISearchController(searchResultsController: nil)
let reciters = [Reciter(name: "Abdul Basit Abdus Samad", downloadUrl: ""),
Reciter(name: "Abdul Rahman Al-Sudais", downloadUrl: ""),
Reciter(name: "Ali Bin Abdur Rahman Al Huthaify", downloadUrl: ""),
Reciter(name: "Mishary Rashid Alafasy", downloadUrl: ""),
Reciter(name: "Cheik Mohamed Jibril", downloadUrl: ""),
Reciter(name: "Mohamed Siddiq El-Minshawi", downloadUrl: ""),
Reciter(name: "Mahmoud Khalil Al-Hussary", downloadUrl: ""),
Reciter(name: "Ibrahim Walk (English Only)", downloadUrl: ""),
Reciter(name: "Abu Bakr Al Shatri", downloadUrl: "")]
var filteredReciters = [Reciter]()
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// definesPresentationContext = true
initNavBar()
initTableView()
// Do any additional setup after loading the view.
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.navigationController?.setNavigationBarHidden(true, animated: animated)
}
func initNavBar() {
// show navbar
self.navigationController?.setNavigationBarHidden(false, animated: true)
// set search bar delegates
searchController.searchResultsUpdater = self
searchController.obscuresBackgroundDuringPresentation = false
// Customize Search Bar
searchController.searchBar.placeholder = "Search Friends"
let myString = "Cancel"
let myAttribute = [ NSAttributedStringKey.foregroundColor: UIColor.white ]
UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).title = myString
UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).setTitleTextAttributes(myAttribute, for: .normal)
if #available(iOS 11.0, *) {
let scb = searchController.searchBar
scb.tintColor = UIColor.white
scb.barTintColor = UIColor.white
if let textfield = scb.value(forKey: "searchField") as? UITextField {
textfield.textColor = UIColor.blue
if let backgroundview = textfield.subviews.first {
// Background color
backgroundview.backgroundColor = UIColor.white
// Rounded corner
backgroundview.layer.cornerRadius = 10
backgroundview.clipsToBounds = true
}
}
}
// Set search bar on navbar
navigationItem.searchController = searchController
navigationItem.hidesSearchBarWhenScrolling = false
}
func initTableView() {
tableView.dataSource = self
tableView.delegate = self
tableView.register(UINib(nibName: "SuraSearchCell", bundle: nil), forCellReuseIdentifier: "SuraSearchCell")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func searchBarIsEmpty() -> Bool {
// Returns true if the text is empty or nil
return searchController.searchBar.text?.isEmpty ?? true
}
func filterContentForSearchText(_ searchText: String, scope: String = "All") {
filteredReciters = reciters.filter({( reciter : Reciter) -> Bool in
return reciter.name.lowercased().contains(searchText.lowercased())
})
tableView.reloadData()
}
func isFiltering() -> Bool {
return searchController.isActive && !searchBarIsEmpty()
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
extension SuraSearchController: UITableViewDataSource, UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if isFiltering() {
return filteredReciters.count
}
return reciters.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "SuraSearchCell", for: indexPath) as? SuraSearchCell {
let candy: Reciter
if isFiltering() {
candy = filteredReciters[indexPath.row]
} else {
candy = reciters[indexPath.row]
}
cell.textLabel!.text = candy.name
return cell
}
return UITableViewCell()
}
}
extension SuraSearchController: UISearchResultsUpdating {
// MARK: - UISearchResultsUpdating Delegate
func updateSearchResults(for searchController: UISearchController) {
filterContentForSearchText(searchController.searchBar.text!)
}
}
以及表格视图单元格的代码
import UIKit
class SuraSearchCell: UITableViewCell {
@IBOutlet weak var itemTitle: UILabel!
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
}
func configureCell(item: Reciter) {
itemTitle.text = item.name
}
}
cell.textLabel
默认为 UITableViewCell
属性。您只需要为 customCell
itemTitle
标签设置值。
将 cell.textLabel!.text = candy.name
替换为 cell. itemTitle!.text = candy.name
,如下所示。
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "SuraSearchCell", for: indexPath) as? SuraSearchCell {
let candy: Reciter
if isFiltering() {
candy = filteredReciters[indexPath.row]
} else {
candy = reciters[indexPath.row]
}
cell. itemTitle!.text = candy.name
//OR
cell.configureCell(candy) // IF your candy is of Reciter type
return cell
}
return UITableViewCell()
}
重用标识符名称可能有误。将名称与代码中使用的名称匹配。
让 cellForRowAtIndex
更新如下
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "SuraSearchCell", for: indexPath) as? SuraSearchCell {
let candy: Reciter
if isFiltering() {
candy = filteredReciters[indexPath.row]
} else {
candy = reciters[indexPath.row]
}
cell.configureCell(candy)
return cell
}
return UITableViewCell()
}